Skip to main content

gmssl_rs_sys/
lib.rs

1// gmssl-sys: Low-level FFI bindings to libgmssl
2//
3// All extern "C" function declarations and #[repr(C)] type definitions
4// are organized by algorithm, matching the GmSSL 3.1 header structure.
5// See https://github.com/guanzhi/GmSSL
6
7#![allow(non_camel_case_types, non_snake_case, dead_code, clippy::missing_safety_doc)]
8
9use libc::{c_char, c_int, c_uint, c_void, FILE, size_t, time_t};
10
11// ============================================================================
12// Version
13// ============================================================================
14
15pub const GMSSL_VERSION_NUM: c_int = 30103;
16
17extern "C" {
18    pub fn gmssl_version_num() -> c_int;
19    pub fn gmssl_version_str() -> *const c_char;
20}
21
22// ============================================================================
23// Random
24// ============================================================================
25
26pub const RAND_BYTES_MAX_SIZE: usize = 256;
27
28extern "C" {
29    pub fn rand_bytes(buf: *mut u8, buflen: size_t) -> c_int;
30}
31
32// ============================================================================
33// SM3 Hash
34// ============================================================================
35
36pub const SM3_DIGEST_SIZE: usize = 32;
37pub const SM3_BLOCK_SIZE: usize = 64;
38pub const SM3_STATE_WORDS: usize = 8;
39pub const SM3_HMAC_SIZE: usize = SM3_DIGEST_SIZE;
40
41pub const SM3_PBKDF2_MIN_ITER: usize = 10000;
42pub const SM3_PBKDF2_MAX_ITER: usize = 16777216 - 1;
43pub const SM3_PBKDF2_MAX_SALT_SIZE: usize = 64;
44pub const SM3_PBKDF2_DEFAULT_SALT_SIZE: usize = 8;
45
46#[repr(C)]
47#[derive(Debug)]
48pub struct SM3_CTX {
49    pub digest: [u32; SM3_STATE_WORDS],
50    pub nblocks: u64,
51    pub block: [u8; SM3_BLOCK_SIZE],
52    pub num: size_t,
53}
54
55#[repr(C)]
56#[derive(Debug)]
57pub struct SM3_HMAC_CTX {
58    pub sm3_ctx: SM3_CTX,
59    pub key: [u8; SM3_BLOCK_SIZE],
60}
61
62#[repr(C)]
63#[derive(Debug)]
64pub struct SM3_KDF_CTX {
65    pub sm3_ctx: SM3_CTX,
66    pub outlen: size_t,
67}
68
69extern "C" {
70    pub fn sm3_init(ctx: *mut SM3_CTX);
71    pub fn sm3_update(ctx: *mut SM3_CTX, data: *const u8, datalen: size_t);
72    pub fn sm3_finish(ctx: *mut SM3_CTX, dgst: *mut u8);
73
74    pub fn sm3_hmac_init(ctx: *mut SM3_HMAC_CTX, key: *const u8, keylen: size_t);
75    pub fn sm3_hmac_update(ctx: *mut SM3_HMAC_CTX, data: *const u8, datalen: size_t);
76    pub fn sm3_hmac_finish(ctx: *mut SM3_HMAC_CTX, mac: *mut u8);
77
78    pub fn pbkdf2_hmac_sm3_genkey(
79        pass: *const c_char,
80        passlen: size_t,
81        salt: *const u8,
82        saltlen: size_t,
83        iter: size_t,
84        outlen: size_t,
85        out: *mut u8,
86    ) -> c_int;
87
88    pub fn sm3_kdf_init(ctx: *mut SM3_KDF_CTX, outlen: size_t);
89    pub fn sm3_kdf_update(ctx: *mut SM3_KDF_CTX, in_: *const u8, inlen: size_t);
90    pub fn sm3_kdf_finish(ctx: *mut SM3_KDF_CTX, out: *mut u8);
91}
92
93// ============================================================================
94// SM4 Block Cipher
95// ============================================================================
96
97pub const SM4_KEY_SIZE: usize = 16;
98pub const SM4_BLOCK_SIZE: usize = 16;
99pub const SM4_NUM_ROUNDS: usize = 32;
100
101pub const SM4_GCM_MAX_IV_SIZE: usize = 64;
102pub const SM4_GCM_MIN_IV_SIZE: usize = 1;
103pub const SM4_GCM_DEFAULT_IV_SIZE: usize = 12;
104pub const SM4_GCM_MIN_AAD_SIZE: usize = 0;
105pub const SM4_GCM_MAX_AAD_SIZE: usize = 1 << 24;
106pub const SM4_GCM_MIN_PLAINTEXT_SIZE: usize = 0;
107pub const SM4_GCM_MAX_TAG_SIZE: usize = 16;
108pub const SM4_GCM_MIN_TAG_SIZE: usize = 12;
109pub const SM4_GCM_DEFAULT_TAG_SIZE: usize = 16;
110
111#[repr(C)]
112#[derive(Debug)]
113pub struct SM4_KEY {
114    pub rk: [u32; SM4_NUM_ROUNDS],
115}
116
117#[repr(C)]
118#[derive(Debug)]
119pub struct SM4_CBC_CTX {
120    pub sm4_key: SM4_KEY,
121    pub iv: [u8; SM4_BLOCK_SIZE],
122    pub block: [u8; SM4_BLOCK_SIZE],
123    pub block_nbytes: size_t,
124}
125
126#[repr(C)]
127#[derive(Debug)]
128pub struct SM4_CTR_CTX {
129    pub sm4_key: SM4_KEY,
130    pub ctr: [u8; SM4_BLOCK_SIZE],
131    pub block: [u8; SM4_BLOCK_SIZE],
132    pub block_nbytes: size_t,
133}
134
135// Forward declaration for GHASH_CTX (used by SM4_GCM_CTX)
136#[repr(C)]
137pub struct GHASH_CTX {
138    _private: [u8; 272],
139}
140
141#[repr(C)]
142pub struct SM4_GCM_CTX {
143    pub enc_ctx: SM4_CTR_CTX,
144    pub mac_ctx: GHASH_CTX,
145    pub Y: [u8; 16],
146    pub taglen: size_t,
147    pub mac: [u8; 16],
148    pub maclen: size_t,
149    pub encedlen: u64,
150}
151
152extern "C" {
153    pub fn sm4_set_encrypt_key(key: *mut SM4_KEY, raw_key: *const u8);
154    pub fn sm4_set_decrypt_key(key: *mut SM4_KEY, raw_key: *const u8);
155    pub fn sm4_encrypt(key: *const SM4_KEY, in_: *const u8, out: *mut u8);
156
157    // One-shot padded CBC
158    pub fn sm4_cbc_padding_encrypt(
159        key: *const SM4_KEY,
160        iv: *const u8,
161        in_: *const u8,
162        inlen: size_t,
163        out: *mut u8,
164        outlen: *mut size_t,
165    ) -> c_int;
166    pub fn sm4_cbc_padding_decrypt(
167        key: *const SM4_KEY,
168        iv: *const u8,
169        in_: *const u8,
170        inlen: size_t,
171        out: *mut u8,
172        outlen: *mut size_t,
173    ) -> c_int;
174
175    // Streaming CBC
176    pub fn sm4_cbc_encrypt_init(
177        ctx: *mut SM4_CBC_CTX,
178        key: *const u8,
179        iv: *const u8,
180    ) -> c_int;
181    pub fn sm4_cbc_encrypt_update(
182        ctx: *mut SM4_CBC_CTX,
183        in_: *const u8,
184        inlen: size_t,
185        out: *mut u8,
186        outlen: *mut size_t,
187    ) -> c_int;
188    pub fn sm4_cbc_encrypt_finish(
189        ctx: *mut SM4_CBC_CTX,
190        out: *mut u8,
191        outlen: *mut size_t,
192    ) -> c_int;
193    pub fn sm4_cbc_decrypt_init(
194        ctx: *mut SM4_CBC_CTX,
195        key: *const u8,
196        iv: *const u8,
197    ) -> c_int;
198    pub fn sm4_cbc_decrypt_update(
199        ctx: *mut SM4_CBC_CTX,
200        in_: *const u8,
201        inlen: size_t,
202        out: *mut u8,
203        outlen: *mut size_t,
204    ) -> c_int;
205    pub fn sm4_cbc_decrypt_finish(
206        ctx: *mut SM4_CBC_CTX,
207        out: *mut u8,
208        outlen: *mut size_t,
209    ) -> c_int;
210
211    // One-shot CTR
212    pub fn sm4_ctr_encrypt(
213        key: *const SM4_KEY,
214        ctr: *mut u8,
215        in_: *const u8,
216        inlen: size_t,
217        out: *mut u8,
218    );
219
220    // Streaming CTR
221    pub fn sm4_ctr_encrypt_init(
222        ctx: *mut SM4_CTR_CTX,
223        key: *const u8,
224        ctr: *const u8,
225    ) -> c_int;
226    pub fn sm4_ctr_encrypt_update(
227        ctx: *mut SM4_CTR_CTX,
228        in_: *const u8,
229        inlen: size_t,
230        out: *mut u8,
231        outlen: *mut size_t,
232    ) -> c_int;
233    pub fn sm4_ctr_encrypt_finish(
234        ctx: *mut SM4_CTR_CTX,
235        out: *mut u8,
236        outlen: *mut size_t,
237    ) -> c_int;
238
239    // One-shot GCM
240    pub fn sm4_gcm_encrypt(
241        key: *const SM4_KEY,
242        iv: *const u8,
243        ivlen: size_t,
244        aad: *const u8,
245        aadlen: size_t,
246        in_: *const u8,
247        inlen: size_t,
248        out: *mut u8,
249        taglen: size_t,
250        tag: *mut u8,
251    ) -> c_int;
252    pub fn sm4_gcm_decrypt(
253        key: *const SM4_KEY,
254        iv: *const u8,
255        ivlen: size_t,
256        aad: *const u8,
257        aadlen: size_t,
258        in_: *const u8,
259        inlen: size_t,
260        tag: *const u8,
261        taglen: size_t,
262        out: *mut u8,
263    ) -> c_int;
264
265    // Streaming GCM
266    pub fn sm4_gcm_encrypt_init(
267        ctx: *mut SM4_GCM_CTX,
268        key: *const u8,
269        keylen: size_t,
270        iv: *const u8,
271        ivlen: size_t,
272        aad: *const u8,
273        aadlen: size_t,
274        taglen: size_t,
275    ) -> c_int;
276    pub fn sm4_gcm_encrypt_update(
277        ctx: *mut SM4_GCM_CTX,
278        in_: *const u8,
279        inlen: size_t,
280        out: *mut u8,
281        outlen: *mut size_t,
282    ) -> c_int;
283    pub fn sm4_gcm_encrypt_finish(
284        ctx: *mut SM4_GCM_CTX,
285        out: *mut u8,
286        outlen: *mut size_t,
287    ) -> c_int;
288    pub fn sm4_gcm_decrypt_init(
289        ctx: *mut SM4_GCM_CTX,
290        key: *const u8,
291        keylen: size_t,
292        iv: *const u8,
293        ivlen: size_t,
294        aad: *const u8,
295        aadlen: size_t,
296        taglen: size_t,
297    ) -> c_int;
298    pub fn sm4_gcm_decrypt_update(
299        ctx: *mut SM4_GCM_CTX,
300        in_: *const u8,
301        inlen: size_t,
302        out: *mut u8,
303        outlen: *mut size_t,
304    ) -> c_int;
305    pub fn sm4_gcm_decrypt_finish(
306        ctx: *mut SM4_GCM_CTX,
307        out: *mut u8,
308        outlen: *mut size_t,
309    ) -> c_int;
310}
311
312// ============================================================================
313// SM2 Public Key Cryptography
314// ============================================================================
315
316pub const SM2_DEFAULT_ID: &[u8; 16] = b"1234567812345678";
317pub const SM2_DEFAULT_ID_LENGTH: usize = 16;
318pub const SM2_MAX_ID_BITS: usize = 65535;
319pub const SM2_MAX_ID_LENGTH: usize = SM2_MAX_ID_BITS / 8;
320
321pub const SM2_MIN_SIGNATURE_SIZE: usize = 8;
322pub const SM2_MAX_SIGNATURE_SIZE: usize = 72;
323pub const SM2_MIN_PLAINTEXT_SIZE: usize = 1;
324pub const SM2_MAX_PLAINTEXT_SIZE: usize = 255;
325pub const SM2_MIN_CIPHERTEXT_SIZE: usize = 45;
326pub const SM2_MAX_CIPHERTEXT_SIZE: usize = 366;
327
328pub const SM2_SIGN_PRE_COMP_COUNT: usize = 32;
329
330pub type sm2_z256_t = [u64; 4];
331
332#[repr(C)]
333#[derive(Debug, Copy, Clone)]
334pub struct SM2_Z256_POINT {
335    pub X: sm2_z256_t,
336    pub Y: sm2_z256_t,
337    pub Z: sm2_z256_t,
338}
339
340#[repr(C)]
341#[derive(Debug)]
342pub struct SM2_KEY {
343    pub public_key: SM2_Z256_POINT,
344    pub private_key: sm2_z256_t,
345}
346
347#[repr(C)]
348#[derive(Debug)]
349pub struct SM2_SIGNATURE {
350    pub r: [u8; 32],
351    pub s: [u8; 32],
352}
353
354#[repr(C)]
355pub struct SM2_POINT {
356    pub x: [u8; 32],
357    pub y: [u8; 32],
358}
359
360#[repr(C)]
361pub struct SM2_CIPHERTEXT {
362    pub point: SM2_POINT,
363    pub hash: [u8; 32],
364    pub ciphertext_size: u8,
365    pub ciphertext: [u8; SM2_MAX_PLAINTEXT_SIZE],
366}
367
368#[repr(C)]
369pub struct SM2_SIGN_PRE_COMP {
370    pub k: sm2_z256_t,
371    pub x1_modn: sm2_z256_t,
372}
373
374#[repr(C)]
375pub struct SM2_SIGN_CTX {
376    pub sm3_ctx: SM3_CTX,
377    pub saved_sm3_ctx: SM3_CTX,
378    pub key: SM2_KEY,
379    pub fast_sign_private: sm2_z256_t,
380    pub pre_comp: [SM2_SIGN_PRE_COMP; SM2_SIGN_PRE_COMP_COUNT],
381    pub num_pre_comp: c_uint,
382    pub public_point_table: [SM2_Z256_POINT; 16],
383}
384
385#[repr(C)]
386pub struct SM2_VERIFY_CTX {
387    pub sm3_ctx: SM3_CTX,
388    pub saved_sm3_ctx: SM3_CTX,
389    pub key: SM2_KEY,
390    pub public_point_table: [SM2_Z256_POINT; 16],
391}
392
393#[repr(C)]
394pub struct SM2_ENC_PRE_COMP {
395    pub k: sm2_z256_t,
396    pub C1: SM2_POINT,
397}
398
399pub const SM2_ENC_PRE_COMP_NUM: usize = 8;
400
401#[repr(C)]
402pub struct SM2_ENC_CTX {
403    pub pre_comp: [SM2_ENC_PRE_COMP; SM2_ENC_PRE_COMP_NUM],
404    pub pre_comp_num: size_t,
405    pub buf: [u8; SM2_MAX_PLAINTEXT_SIZE],
406    pub buf_size: size_t,
407}
408
409#[repr(C)]
410pub struct SM2_DEC_CTX {
411    pub buf: [u8; SM2_MAX_CIPHERTEXT_SIZE],
412    pub buf_size: size_t,
413}
414
415extern "C" {
416    // Key generation
417    pub fn sm2_key_generate(key: *mut SM2_KEY) -> c_int;
418
419    // Key import/export (raw)
420    pub fn sm2_public_key_to_der(key: *const SM2_KEY, out: *mut *mut u8, outlen: *mut size_t) -> c_int;
421    pub fn sm2_public_key_from_der(key: *mut SM2_KEY, in_: *mut *const u8, inlen: *mut size_t) -> c_int;
422    pub fn sm2_private_key_to_der(key: *const SM2_KEY, out: *mut *mut u8, outlen: *mut size_t) -> c_int;
423    pub fn sm2_private_key_from_der(key: *mut SM2_KEY, in_: *mut *const u8, inlen: *mut size_t) -> c_int;
424
425    // SubjectPublicKeyInfo DER
426    pub fn sm2_public_key_info_to_der(key: *const SM2_KEY, out: *mut *mut u8, outlen: *mut size_t) -> c_int;
427    pub fn sm2_public_key_info_from_der(key: *mut SM2_KEY, in_: *mut *const u8, inlen: *mut size_t) -> c_int;
428
429    // SubjectPublicKeyInfo PEM
430    pub fn sm2_public_key_info_to_pem(key: *const SM2_KEY, fp: *mut FILE) -> c_int;
431    pub fn sm2_public_key_info_from_pem(key: *mut SM2_KEY, fp: *mut FILE) -> c_int;
432
433    // PKCS#8 PrivateKeyInfo DER
434    pub fn sm2_private_key_info_to_der(key: *const SM2_KEY, out: *mut *mut u8, outlen: *mut size_t) -> c_int;
435    pub fn sm2_private_key_info_from_der(
436        key: *mut SM2_KEY,
437        attrs: *mut *const u8,
438        attrslen: *mut size_t,
439        in_: *mut *const u8,
440        inlen: *mut size_t,
441    ) -> c_int;
442
443    // PKCS#8 PrivateKeyInfo PEM
444    pub fn sm2_private_key_info_to_pem(key: *const SM2_KEY, fp: *mut FILE) -> c_int;
445    pub fn sm2_private_key_info_from_pem(key: *mut SM2_KEY, fp: *mut FILE) -> c_int;
446
447    // Encrypted PKCS#8 DER
448    pub fn sm2_private_key_info_encrypt_to_der(
449        key: *const SM2_KEY,
450        pass: *const c_char,
451        out: *mut *mut u8,
452        outlen: *mut size_t,
453    ) -> c_int;
454    pub fn sm2_private_key_info_decrypt_from_der(
455        key: *mut SM2_KEY,
456        attrs: *mut *const u8,
457        attrs_len: *mut size_t,
458        pass: *const c_char,
459        in_: *mut *const u8,
460        inlen: *mut size_t,
461    ) -> c_int;
462
463    // Encrypted PKCS#8 PEM
464    pub fn sm2_private_key_info_encrypt_to_pem(
465        key: *const SM2_KEY,
466        pass: *const c_char,
467        fp: *mut FILE,
468    ) -> c_int;
469    pub fn sm2_private_key_info_decrypt_from_pem(
470        key: *mut SM2_KEY,
471        pass: *const c_char,
472        fp: *mut FILE,
473    ) -> c_int;
474
475    // Compute Z value
476    pub fn sm2_compute_z(
477        z: *mut u8,
478        pub_: *const SM2_Z256_POINT,
479        id: *const c_char,
480        idlen: size_t,
481    ) -> c_int;
482
483    // Sign/verify (one-shot with pre-computed digest)
484    pub fn sm2_sign(key: *const SM2_KEY, dgst: *const u8, sig: *mut u8, siglen: *mut size_t) -> c_int;
485    pub fn sm2_verify(key: *const SM2_KEY, dgst: *const u8, sig: *const u8, siglen: size_t) -> c_int;
486
487    // Streaming sign/verify
488    pub fn sm2_sign_init(
489        ctx: *mut SM2_SIGN_CTX,
490        key: *const SM2_KEY,
491        id: *const c_char,
492        idlen: size_t,
493    ) -> c_int;
494    pub fn sm2_sign_update(ctx: *mut SM2_SIGN_CTX, data: *const u8, datalen: size_t) -> c_int;
495    pub fn sm2_sign_finish(ctx: *mut SM2_SIGN_CTX, sig: *mut u8, siglen: *mut size_t) -> c_int;
496
497    pub fn sm2_verify_init(
498        ctx: *mut SM2_VERIFY_CTX,
499        key: *const SM2_KEY,
500        id: *const c_char,
501        idlen: size_t,
502    ) -> c_int;
503    pub fn sm2_verify_update(ctx: *mut SM2_VERIFY_CTX, data: *const u8, datalen: size_t) -> c_int;
504    pub fn sm2_verify_finish(ctx: *mut SM2_VERIFY_CTX, sig: *const u8, siglen: size_t) -> c_int;
505
506    // Encrypt/decrypt (one-shot)
507    pub fn sm2_encrypt(
508        key: *const SM2_KEY,
509        in_: *const u8,
510        inlen: size_t,
511        out: *mut u8,
512        outlen: *mut size_t,
513    ) -> c_int;
514    pub fn sm2_decrypt(
515        key: *const SM2_KEY,
516        in_: *const u8,
517        inlen: size_t,
518        out: *mut u8,
519        outlen: *mut size_t,
520    ) -> c_int;
521
522    // KDF
523    pub fn sm2_kdf(in_: *const u8, inlen: size_t, outlen: size_t, out: *mut u8) -> c_int;
524
525    // ECDH
526    pub fn sm2_do_ecdh(
527        key: *const SM2_KEY,
528        peer_key: *const SM2_KEY,
529        out: *mut u8,
530    ) -> c_int;
531    pub fn sm2_ecdh(
532        key: *const SM2_KEY,
533        uncompressed_point: *const u8,
534        out: *mut u8,
535    ) -> c_int;
536}
537
538// ============================================================================
539// SM9 Identity-Based Cryptography
540// ============================================================================
541
542pub const SM9_HID_SIGN: u8 = 0x01;
543pub const SM9_HID_ENC: u8 = 0x03;
544pub const SM9_MAX_ID_SIZE: usize = SM2_MAX_ID_LENGTH;
545pub const SM9_MAX_SIGNATURE_SIZE: usize = 104;
546pub const SM9_MAX_PLAINTEXT_SIZE: usize = 255;
547pub const SM9_MAX_CIPHERTEXT_SIZE: usize = 367;
548pub const SM9_SIGNATURE_SIZE: usize = 104;
549
550// sm9_z256_t is different from sm2_z256_t
551pub type sm9_z256_t = [u64; 4];
552
553#[repr(C)]
554pub struct SM9_Z256_TWIST_POINT {
555    pub X: sm9_z256_t,
556    pub Y: sm9_z256_t,
557    pub Z: sm9_z256_t,
558}
559
560// SM9_Z256_POINT is same as SM2_Z256_POINT for SM9
561pub type SM9_Z256_POINT = SM2_Z256_POINT;
562
563#[repr(C)]
564pub struct SM9_SIGN_MASTER_KEY {
565    pub Ppubs: SM9_Z256_TWIST_POINT,
566    pub ks: sm9_z256_t,
567}
568
569#[repr(C)]
570pub struct SM9_SIGN_KEY {
571    pub Ppubs: SM9_Z256_TWIST_POINT,
572    pub ds: SM9_Z256_POINT,
573}
574
575#[repr(C)]
576pub struct SM9_SIGNATURE {
577    pub h: sm9_z256_t,
578    pub S: SM9_Z256_POINT,
579}
580
581#[repr(C)]
582pub struct SM9_ENC_MASTER_KEY {
583    pub Ppube: SM9_Z256_POINT,
584    pub ke: sm9_z256_t,
585}
586
587#[repr(C)]
588pub struct SM9_ENC_KEY {
589    pub Ppube: SM9_Z256_POINT,
590    pub de: SM9_Z256_TWIST_POINT,
591}
592
593#[repr(C)]
594pub struct SM9_SIGN_CTX {
595    pub sm3_ctx: SM3_CTX,
596}
597
598extern "C" {
599    // SM9 Sign master key
600    pub fn sm9_sign_master_key_generate(master: *mut SM9_SIGN_MASTER_KEY) -> c_int;
601    pub fn sm9_sign_master_key_extract_key(
602        master: *const SM9_SIGN_MASTER_KEY,
603        id: *const c_char,
604        idlen: size_t,
605        key: *mut SM9_SIGN_KEY,
606    ) -> c_int;
607    pub fn sm9_sign_master_key_info_encrypt_to_der(
608        msk: *const SM9_SIGN_MASTER_KEY,
609        pass: *const c_char,
610        out: *mut *mut u8,
611        outlen: *mut size_t,
612    ) -> c_int;
613    pub fn sm9_sign_master_key_info_decrypt_from_der(
614        msk: *mut SM9_SIGN_MASTER_KEY,
615        pass: *const c_char,
616        in_: *mut *const u8,
617        inlen: *mut size_t,
618    ) -> c_int;
619    pub fn sm9_sign_master_key_info_encrypt_to_pem(
620        msk: *const SM9_SIGN_MASTER_KEY,
621        pass: *const c_char,
622        fp: *mut FILE,
623    ) -> c_int;
624    pub fn sm9_sign_master_key_info_decrypt_from_pem(
625        msk: *mut SM9_SIGN_MASTER_KEY,
626        pass: *const c_char,
627        fp: *mut FILE,
628    ) -> c_int;
629    pub fn sm9_sign_master_public_key_to_pem(
630        mpk: *const SM9_SIGN_MASTER_KEY,
631        fp: *mut FILE,
632    ) -> c_int;
633    pub fn sm9_sign_master_public_key_from_pem(
634        mpk: *mut SM9_SIGN_MASTER_KEY,
635        fp: *mut FILE,
636    ) -> c_int;
637
638    // SM9 Sign user key
639    pub fn sm9_sign_key_info_encrypt_to_der(
640        key: *const SM9_SIGN_KEY,
641        pass: *const c_char,
642        out: *mut *mut u8,
643        outlen: *mut size_t,
644    ) -> c_int;
645    pub fn sm9_sign_key_info_decrypt_from_der(
646        key: *mut SM9_SIGN_KEY,
647        pass: *const c_char,
648        in_: *mut *const u8,
649        inlen: *mut size_t,
650    ) -> c_int;
651    pub fn sm9_sign_key_info_encrypt_to_pem(
652        key: *const SM9_SIGN_KEY,
653        pass: *const c_char,
654        fp: *mut FILE,
655    ) -> c_int;
656    pub fn sm9_sign_key_info_decrypt_from_pem(
657        key: *mut SM9_SIGN_KEY,
658        pass: *const c_char,
659        fp: *mut FILE,
660    ) -> c_int;
661
662    // SM9 Sign/Verify
663    pub fn sm9_sign_init(ctx: *mut SM9_SIGN_CTX) -> c_int;
664    pub fn sm9_sign_update(ctx: *mut SM9_SIGN_CTX, data: *const u8, datalen: size_t) -> c_int;
665    pub fn sm9_sign_finish(
666        ctx: *mut SM9_SIGN_CTX,
667        key: *const SM9_SIGN_KEY,
668        sig: *mut u8,
669        siglen: *mut size_t,
670    ) -> c_int;
671    pub fn sm9_verify_init(ctx: *mut SM9_SIGN_CTX) -> c_int;
672    pub fn sm9_verify_update(ctx: *mut SM9_SIGN_CTX, data: *const u8, datalen: size_t) -> c_int;
673    pub fn sm9_verify_finish(
674        ctx: *mut SM9_SIGN_CTX,
675        sig: *const u8,
676        siglen: size_t,
677        mpk: *const SM9_SIGN_MASTER_KEY,
678        id: *const c_char,
679        idlen: size_t,
680    ) -> c_int;
681
682    // SM9 Enc master key
683    pub fn sm9_enc_master_key_generate(master: *mut SM9_ENC_MASTER_KEY) -> c_int;
684    pub fn sm9_enc_master_key_extract_key(
685        master: *const SM9_ENC_MASTER_KEY,
686        id: *const c_char,
687        idlen: size_t,
688        key: *mut SM9_ENC_KEY,
689    ) -> c_int;
690    pub fn sm9_enc_master_key_info_encrypt_to_der(
691        msk: *const SM9_ENC_MASTER_KEY,
692        pass: *const c_char,
693        out: *mut *mut u8,
694        outlen: *mut size_t,
695    ) -> c_int;
696    pub fn sm9_enc_master_key_info_decrypt_from_der(
697        msk: *mut SM9_ENC_MASTER_KEY,
698        pass: *const c_char,
699        in_: *mut *const u8,
700        inlen: *mut size_t,
701    ) -> c_int;
702    pub fn sm9_enc_master_key_info_encrypt_to_pem(
703        msk: *const SM9_ENC_MASTER_KEY,
704        pass: *const c_char,
705        fp: *mut FILE,
706    ) -> c_int;
707    pub fn sm9_enc_master_key_info_decrypt_from_pem(
708        msk: *mut SM9_ENC_MASTER_KEY,
709        pass: *const c_char,
710        fp: *mut FILE,
711    ) -> c_int;
712    pub fn sm9_enc_master_public_key_to_pem(
713        mpk: *const SM9_ENC_MASTER_KEY,
714        fp: *mut FILE,
715    ) -> c_int;
716    pub fn sm9_enc_master_public_key_from_pem(
717        mpk: *mut SM9_ENC_MASTER_KEY,
718        fp: *mut FILE,
719    ) -> c_int;
720
721    // SM9 Enc user key
722    pub fn sm9_enc_key_info_encrypt_to_der(
723        key: *const SM9_ENC_KEY,
724        pass: *const c_char,
725        out: *mut *mut u8,
726        outlen: *mut size_t,
727    ) -> c_int;
728    pub fn sm9_enc_key_info_decrypt_from_der(
729        key: *mut SM9_ENC_KEY,
730        pass: *const c_char,
731        in_: *mut *const u8,
732        inlen: *mut size_t,
733    ) -> c_int;
734    pub fn sm9_enc_key_info_encrypt_to_pem(
735        key: *const SM9_ENC_KEY,
736        pass: *const c_char,
737        fp: *mut FILE,
738    ) -> c_int;
739    pub fn sm9_enc_key_info_decrypt_from_pem(
740        key: *mut SM9_ENC_KEY,
741        pass: *const c_char,
742        fp: *mut FILE,
743    ) -> c_int;
744
745    // SM9 Encrypt/Decrypt
746    pub fn sm9_encrypt(
747        mpk: *const SM9_ENC_MASTER_KEY,
748        id: *const c_char,
749        idlen: size_t,
750        in_: *const u8,
751        inlen: size_t,
752        out: *mut u8,
753        outlen: *mut size_t,
754    ) -> c_int;
755    pub fn sm9_decrypt(
756        key: *const SM9_ENC_KEY,
757        id: *const c_char,
758        idlen: size_t,
759        in_: *const u8,
760        inlen: size_t,
761        out: *mut u8,
762        outlen: *mut size_t,
763    ) -> c_int;
764}
765
766// ============================================================================
767// X.509 Certificates
768// ============================================================================
769
770// X509_KEY is a union type with cleanup needed
771#[repr(C)]
772pub struct X509_KEY {
773    data: [u8; 8192], // oversize opaque; exact size from header is large due to unions
774}
775
776extern "C" {
777    pub fn x509_key_set_sm2_key(x509_key: *mut X509_KEY, sm2_key: *const SM2_KEY) -> c_int;
778    pub fn x509_key_generate(key: *mut X509_KEY, algor: c_int, param: *const c_void, paramlen: size_t) -> c_int;
779    pub fn x509_key_cleanup(key: *mut X509_KEY);
780    pub fn x509_public_key_info_to_der(key: *const X509_KEY, out: *mut *mut u8, outlen: *mut size_t) -> c_int;
781    pub fn x509_public_key_info_from_der(key: *mut X509_KEY, in_: *mut *const u8, inlen: *mut size_t) -> c_int;
782    pub fn x509_public_key_info_to_pem(key: *const X509_KEY, fp: *mut FILE) -> c_int;
783    pub fn x509_public_key_info_from_pem(key: *mut X509_KEY, fp: *mut FILE) -> c_int;
784}
785
786// X.509 Certificate operations (cert is raw DER bytes)
787extern "C" {
788    // Certificate to/from DER
789    pub fn x509_cert_to_der(a: *const u8, alen: size_t, out: *mut *mut u8, outlen: *mut size_t) -> c_int;
790    pub fn x509_cert_from_der(
791        a: *mut *const u8,
792        alen: *mut size_t,
793        in_: *mut *const u8,
794        inlen: *mut size_t,
795    ) -> c_int;
796
797    // Certificate to/from PEM
798    pub fn x509_cert_to_pem(a: *const u8, alen: size_t, fp: *mut FILE) -> c_int;
799    pub fn x509_cert_from_pem(
800        a: *mut u8,
801        alen: *mut size_t,
802        maxlen: size_t,
803        fp: *mut FILE,
804    ) -> c_int;
805
806    // Certificate details
807    pub fn x509_cert_get_details(
808        a: *const u8,
809        alen: size_t,
810        version: *mut c_int,
811        serial: *mut *const u8,
812        serial_len: *mut size_t,
813        issuer: *mut *const u8,
814        issuer_len: *mut size_t,
815        not_before: *mut time_t,
816        not_after: *mut time_t,
817        subject: *mut *const u8,
818        subject_len: *mut size_t,
819        public_key: *mut X509_KEY,
820        signature_algor: *mut c_int,
821        signature: *mut *const u8,
822        signature_len: *mut size_t,
823    ) -> c_int;
824
825    // Get individual certificate fields
826    pub fn x509_cert_get_subject(
827        a: *const u8,
828        alen: size_t,
829        subj: *mut *const u8,
830        subj_len: *mut size_t,
831    ) -> c_int;
832    pub fn x509_cert_get_issuer(
833        a: *const u8,
834        alen: size_t,
835        name: *mut *const u8,
836        namelen: *mut size_t,
837    ) -> c_int;
838    pub fn x509_cert_get_subject_public_key(
839        a: *const u8,
840        alen: size_t,
841        public_key: *mut X509_KEY,
842    ) -> c_int;
843    pub fn x509_cert_get_signature_algor(
844        a: *const u8,
845        alen: size_t,
846        oid: *mut c_int,
847    ) -> c_int;
848
849    // Verify cert by CA cert
850    pub fn x509_cert_verify_by_ca_cert(
851        a: *const u8,
852        alen: size_t,
853        cacert: *const u8,
854        cacertlen: size_t,
855        signer_id: *const c_char,
856        signer_id_len: size_t,
857    ) -> c_int;
858
859    // Certificate chain operations
860    pub fn x509_certs_to_pem(d: *const u8, dlen: size_t, fp: *mut FILE) -> c_int;
861    pub fn x509_certs_from_pem(
862        d: *mut u8,
863        dlen: *mut size_t,
864        maxlen: size_t,
865        fp: *mut FILE,
866    ) -> c_int;
867    pub fn x509_certs_get_count(d: *const u8, dlen: size_t, cnt: *mut size_t) -> c_int;
868    pub fn x509_certs_get_cert_by_index(
869        d: *const u8,
870        dlen: size_t,
871        index: c_int,
872        cert: *mut *const u8,
873        certlen: *mut size_t,
874    ) -> c_int;
875    pub fn x509_certs_get_last(
876        d: *const u8,
877        dlen: size_t,
878        cert: *mut *const u8,
879        certlen: *mut size_t,
880    ) -> c_int;
881    pub fn x509_certs_verify(
882        certs: *const u8,
883        certslen: size_t,
884        certs_type: c_int,
885        cacerts: *const u8,
886        cacertslen: size_t,
887        depth: size_t,
888    ) -> c_int;
889
890    // CSR (Certificate Signing Request)
891    pub fn x509_req_sign_to_der(
892        version: c_int,
893        subject: *const u8,
894        subject_len: size_t,
895        subject_public_key: *const X509_KEY,
896        attrs: *const u8,
897        attrs_len: size_t,
898        signature_algor: c_int,
899        sign_key: *mut X509_KEY,
900        signer_id: *const c_char,
901        signer_id_len: size_t,
902        out: *mut *mut u8,
903        outlen: *mut size_t,
904    ) -> c_int;
905    pub fn x509_req_verify(
906        req: *const u8,
907        reqlen: size_t,
908        signer_id: *const c_char,
909        signer_id_len: size_t,
910    ) -> c_int;
911    pub fn x509_req_get_details(
912        req: *const u8,
913        reqlen: size_t,
914        version: *mut c_int,
915        subject: *mut *const u8,
916        subject_len: *mut size_t,
917        subject_public_key: *mut X509_KEY,
918        attributes: *mut *const u8,
919        attributes_len: *mut size_t,
920        signature_algor: *mut c_int,
921        signature: *mut *const u8,
922        signature_len: *mut size_t,
923    ) -> c_int;
924    pub fn x509_req_to_pem(req: *const u8, reqlen: size_t, fp: *mut FILE) -> c_int;
925    pub fn x509_req_from_pem(
926        req: *mut u8,
927        reqlen: *mut size_t,
928        maxlen: size_t,
929        fp: *mut FILE,
930    ) -> c_int;
931    pub fn x509_req_to_der(a: *const u8, alen: size_t, out: *mut *mut u8, outlen: *mut size_t) -> c_int;
932    pub fn x509_req_from_der(
933        a: *mut *const u8,
934        alen: *mut size_t,
935        in_: *mut *const u8,
936        inlen: *mut size_t,
937    ) -> c_int;
938}
939
940// ============================================================================
941// ZUC Stream Cipher
942// ============================================================================
943
944pub const ZUC_KEY_SIZE: usize = 16;
945pub const ZUC_IV_SIZE: usize = 16;
946pub const ZUC_MAC_SIZE: usize = 4;
947
948pub const ZUC256_KEY_SIZE: usize = 32;
949pub const ZUC256_IV_SIZE: usize = 23;
950pub const ZUC256_MAC32_SIZE: usize = 4;
951pub const ZUC256_MAC64_SIZE: usize = 8;
952pub const ZUC256_MAC128_SIZE: usize = 16;
953
954#[repr(C)]
955#[derive(Debug)]
956pub struct ZUC_STATE {
957    pub LFSR: [u32; 16],
958    pub R1: u32,
959    pub R2: u32,
960}
961
962#[repr(C)]
963#[derive(Debug)]
964pub struct ZUC_MAC_CTX {
965    pub LFSR: [u32; 16],
966    pub R1: u32,
967    pub R2: u32,
968    pub T: u32,
969    pub K0: u32,
970    pub buf: [u8; 4],
971    pub buflen: size_t,
972}
973
974#[repr(C)]
975#[derive(Debug)]
976pub struct ZUC256_MAC_CTX {
977    pub LFSR: [u32; 16],
978    pub R1: u32,
979    pub R2: u32,
980    pub T: [u32; 4],
981    pub K0: [u32; 4],
982    pub buf: [u8; 4],
983    pub buflen: size_t,
984    pub macbits: c_int,
985}
986
987#[repr(C)]
988#[derive(Debug)]
989pub struct ZUC_CTX {
990    pub zuc_state: ZUC_STATE,
991    pub block: [u8; 4],
992    pub block_nbytes: size_t,
993}
994
995extern "C" {
996    // ZUC stream cipher
997    pub fn zuc_init(state: *mut ZUC_STATE, key: *const u8, iv: *const u8);
998    pub fn zuc_generate_keystream(state: *mut ZUC_STATE, nwords: size_t, words: *mut u32);
999    pub fn zuc_encrypt(state: *mut ZUC_STATE, in_: *const u8, inlen: size_t, out: *mut u8);
1000
1001    // ZUC MAC
1002    pub fn zuc_mac_init(ctx: *mut ZUC_MAC_CTX, key: *const u8, iv: *const u8);
1003    pub fn zuc_mac_update(ctx: *mut ZUC_MAC_CTX, data: *const u8, len: size_t);
1004    pub fn zuc_mac_finish(
1005        ctx: *mut ZUC_MAC_CTX,
1006        data: *const u8,
1007        nbits: size_t,
1008        mac: *mut u8,
1009    );
1010
1011    // ZUC-256
1012    pub fn zuc256_init(state: *mut ZUC_STATE, key: *const u8, iv: *const u8);
1013    pub fn zuc256_generate_keystream(state: *mut ZUC_STATE, nwords: size_t, words: *mut u32);
1014    pub fn zuc256_mac_init(
1015        ctx: *mut ZUC256_MAC_CTX,
1016        key: *const u8,
1017        iv: *const u8,
1018        macbits: c_int,
1019    );
1020    pub fn zuc256_mac_update(ctx: *mut ZUC256_MAC_CTX, data: *const u8, len: size_t);
1021    pub fn zuc256_mac_finish(
1022        ctx: *mut ZUC256_MAC_CTX,
1023        data: *const u8,
1024        nbits: size_t,
1025        mac: *mut u8,
1026    );
1027
1028    // ZUC streaming
1029    pub fn zuc_encrypt_init(ctx: *mut ZUC_CTX, key: *const u8, iv: *const u8) -> c_int;
1030    pub fn zuc_encrypt_update(
1031        ctx: *mut ZUC_CTX,
1032        in_: *const u8,
1033        inlen: size_t,
1034        out: *mut u8,
1035        outlen: *mut size_t,
1036    ) -> c_int;
1037    pub fn zuc_encrypt_finish(ctx: *mut ZUC_CTX, out: *mut u8, outlen: *mut size_t) -> c_int;
1038}