/*
 * gmcrypto-c — C ABI for gmcrypto-core (pure-Rust SM2/SM3/SM4 SDK).
 *
 * AUTO-GENERATED by cbindgen. DO NOT EDIT BY HAND.
 * Regenerate via: cargo build -p gmcrypto-c --features regen-header
 *
 * Failure-mode invariant (v0.4 W4 / Q4.8 of docs/v0.4-scope.md):
 * every int return is 0 on success, non-zero on failure. Non-zero
 * codes are NOT enumerated — they are equivalent `Failed` per the
 * crate's failure-mode discipline.
 */

#ifndef GMCRYPTO_H_
#define GMCRYPTO_H_

/* Warning: this file is auto-generated by cbindgen; do not edit. */

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>

/*
 Success return code.
 */
#define GMCRYPTO_OK 0

/*
 Generic failure return code. All non-zero returns are equivalent
 per the failure-mode invariant; this constant exists only as a
 convenience for C callers that want a named symbol for the
 not-success case.
 */
#define GMCRYPTO_ERR -1

/*
 SM3 digest output size in bytes (32 = 256 bits).
 */
#define GMCRYPTO_SM3_DIGEST_SIZE 32

/*
 SM4 block size in bytes (16 = 128 bits).
 */
#define GMCRYPTO_SM4_BLOCK_SIZE 16

/*
 SM4 key size in bytes (16 = 128 bits).
 */
#define GMCRYPTO_SM4_KEY_SIZE 16

/*
 SEC1 uncompressed-point size for SM2 public keys
 (`04 || X || Y` = 65 bytes).
 */
#define GMCRYPTO_SM2_SEC1_UNCOMPRESSED_SIZE 65

/*
 SM2 private-key scalar size in bytes (32 = 256 bits big-endian).
 */
#define GMCRYPTO_SM2_SCALAR_SIZE 32

/*
 Opaque handle for a streaming HMAC-SM3 keyed MAC.
 */
typedef struct gmcrypto_hmac_sm3_t gmcrypto_hmac_sm3_t;

/*
 Opaque handle for an SM2 private key.
 */
typedef struct gmcrypto_sm2_privkey_t gmcrypto_sm2_privkey_t;

/*
 Opaque handle for an SM2 public key.
 */
typedef struct gmcrypto_sm2_pubkey_t gmcrypto_sm2_pubkey_t;

/*
 Opaque handle for a streaming SM3 hasher.
 */
typedef struct gmcrypto_sm3_t gmcrypto_sm3_t;

/*
 Opaque handle for an SM4 cipher (key-scheduled).
 */
typedef struct gmcrypto_sm4_t gmcrypto_sm4_t;

/*
 Returns a NUL-terminated string with the `gmcrypto-c` version
 (e.g. `"0.4.0"`). The returned pointer is to a static `&'static
 CStr` and must NOT be freed by the caller.
 */
 const char *gmcrypto_version(void) ;

/*
 Single-shot SM3 hash. Writes 32 bytes to `out_digest`.

 # Returns
 [`GMCRYPTO_OK`] on success; [`GMCRYPTO_ERR`] on invalid input
 (null `out_digest`, null `msg` with non-zero `msg_len`).
 */
 int gmcrypto_sm3_hash(const uint8_t *msg, uintptr_t msg_len, uint8_t *out_digest) ;

/*
 Construct a fresh streaming SM3 hasher. Returns an opaque handle;
 must be freed via [`gmcrypto_sm3_free`].

 Returns NULL on allocation failure.
 */
 gmcrypto_sm3_t *gmcrypto_sm3_new(void) ;

/*
 Absorb `data` into the streaming SM3 hasher.
 */
 int gmcrypto_sm3_update(gmcrypto_sm3_t *hasher, const uint8_t *data, uintptr_t data_len) ;

/*
 Consume the streaming SM3 hasher and write the digest to
 `out_digest`. The handle is **freed** by this call; do not call
 [`gmcrypto_sm3_free`] on it afterwards.
 */
 int gmcrypto_sm3_finalize(gmcrypto_sm3_t *hasher, uint8_t *out_digest) ;

/*
 Free a streaming SM3 hasher. Passing NULL is a no-op.
 */
 void gmcrypto_sm3_free(gmcrypto_sm3_t *hasher) ;

/*
 Single-shot HMAC-SM3. Writes 32 bytes to `out_tag`.
 */

int gmcrypto_hmac_sm3(const uint8_t *key,
                      uintptr_t key_len,
                      const uint8_t *msg,
                      uintptr_t msg_len,
                      uint8_t *out_tag)
;

/*
 Construct a fresh streaming HMAC-SM3 instance keyed with `key`.
 Returns NULL on invalid input.
 */
 gmcrypto_hmac_sm3_t *gmcrypto_hmac_sm3_new(const uint8_t *key, uintptr_t key_len) ;

/*
 Absorb `data` into the streaming HMAC-SM3 instance.
 */
 int gmcrypto_hmac_sm3_update(gmcrypto_hmac_sm3_t *mac, const uint8_t *data, uintptr_t data_len) ;

/*
 Consume the streaming HMAC-SM3 instance and write the 32-byte tag
 to `out_tag`. The handle is **freed** by this call.
 */
 int gmcrypto_hmac_sm3_finalize(gmcrypto_hmac_sm3_t *mac, uint8_t *out_tag) ;

/*
 Consume the streaming HMAC-SM3 instance and verify the candidate
 tag in constant time. Returns [`GMCRYPTO_OK`] on match;
 [`GMCRYPTO_ERR`] on mismatch. The handle is **freed** by this call.
 */
 int gmcrypto_hmac_sm3_verify(gmcrypto_hmac_sm3_t *mac, const uint8_t *expected_tag) ;

/*
 Free a streaming HMAC-SM3 instance. NULL is a no-op.
 */
 void gmcrypto_hmac_sm3_free(gmcrypto_hmac_sm3_t *mac) ;

/*
 Derive `out_len` bytes via PBKDF2-HMAC-SM3 over `(pwd, salt,
 iterations)`. Writes into the caller-supplied `out` buffer.
 */

int gmcrypto_pbkdf2_hmac_sm3(const uint8_t *pwd,
                             uintptr_t pwd_len,
                             const uint8_t *salt,
                             uintptr_t salt_len,
                             uint32_t iterations,
                             uint8_t *out,
                             uintptr_t out_len)
;

/*
 Construct an SM4 cipher from a 16-byte key. Returns NULL on null
 key.
 */
 gmcrypto_sm4_t *gmcrypto_sm4_new(const uint8_t *key) ;

/*
 Encrypt one 16-byte block in place under the SM4 cipher.
 */
 int gmcrypto_sm4_encrypt_block(const gmcrypto_sm4_t *cipher, uint8_t *block) ;

/*
 Decrypt one 16-byte block in place under the SM4 cipher.
 */
 int gmcrypto_sm4_decrypt_block(const gmcrypto_sm4_t *cipher, uint8_t *block) ;

/*
 Free an SM4 cipher. NULL is a no-op.
 */
 void gmcrypto_sm4_free(gmcrypto_sm4_t *cipher) ;

/*
 SM4-CBC single-shot encrypt with PKCS#7 padding. IV must be
 caller-supplied and unpredictable (per NIST SP 800-38A
 Appendix C). Output length is always `((pt_len / 16) + 1) * 16`.
 */

int gmcrypto_sm4_cbc_encrypt(const uint8_t *key,
                             const uint8_t *iv,
                             const uint8_t *pt,
                             uintptr_t pt_len,
                             uint8_t *out,
                             uintptr_t out_capacity,
                             uintptr_t *out_actual_len)
;

/*
 SM4-CBC single-shot decrypt. Single-`Failed` return on any
 failure mode (length not multiple of 16, bad padding, key/IV
 mismatch) per the failure-mode invariant.
 */

int gmcrypto_sm4_cbc_decrypt(const uint8_t *key,
                             const uint8_t *iv,
                             const uint8_t *ct,
                             uintptr_t ct_len,
                             uint8_t *out,
                             uintptr_t out_capacity,
                             uintptr_t *out_actual_len)
;

/*
 Construct an SM2 private key from a 32-byte big-endian scalar.
 Returns NULL on out-of-range scalar (must be in `[1, n-2]`).
 */
 gmcrypto_sm2_privkey_t *gmcrypto_sm2_privkey_new(const uint8_t *d_be) ;

/*
 Construct an SM2 public key from a SEC1 uncompressed-point byte
 string (`04 || X || Y`, 65 bytes). Returns NULL on
 invalid input (off-curve, identity point, non-uncompressed
 prefix).
 */
 gmcrypto_sm2_pubkey_t *gmcrypto_sm2_pubkey_new(const uint8_t *sec1_uncompressed) ;

/*
 Export the SM2 private key as a 32-byte big-endian scalar.

 **Caller MUST zeroize the output buffer** after use. Per Q4.19,
 this entry point exists as `#[doc(hidden)]`-equivalent on the
 Rust side and is NOT SemVer-stable across v0.4.x.
 */
 int gmcrypto_sm2_privkey_to_sec1_be(const gmcrypto_sm2_privkey_t *key, uint8_t *out) ;

/*
 Export the SM2 public key as a SEC1 uncompressed-point byte
 string (`04 || X || Y`, 65 bytes).
 */
 int gmcrypto_sm2_pubkey_to_sec1_uncompressed(const gmcrypto_sm2_pubkey_t *key, uint8_t *out) ;

/*
 Free an SM2 private key. NULL is a no-op. The inner scalar is
 zeroized via `ZeroizeOnDrop` before the heap slot is freed.
 */
 void gmcrypto_sm2_privkey_free(gmcrypto_sm2_privkey_t *key) ;

/*
 Free an SM2 public key. NULL is a no-op.
 */
 void gmcrypto_sm2_pubkey_free(gmcrypto_sm2_pubkey_t *key) ;

/*
 Emit a password-encrypted PKCS#8 PEM blob containing the SM2
 private key. PBES2 / PBKDF2-HMAC-SM3 / SM4-CBC per RFC 8018.
 */

int gmcrypto_sm2_privkey_to_pkcs8(const gmcrypto_sm2_privkey_t *key,
                                  const uint8_t *password,
                                  uintptr_t pwd_len,
                                  uint32_t pbkdf2_iters,
                                  uint8_t *out_pem,
                                  uintptr_t out_capacity,
                                  uintptr_t *out_actual_len)
;

/*
 Load an SM2 private key from a password-encrypted PKCS#8 PEM blob.
 On success, writes the new handle to `*out_key` and returns
 [`GMCRYPTO_OK`]. Caller MUST free via [`gmcrypto_sm2_privkey_free`].
 */

int gmcrypto_sm2_privkey_from_pkcs8(const uint8_t *pem,
                                    uintptr_t pem_len,
                                    const uint8_t *password,
                                    uintptr_t pwd_len,
                                    gmcrypto_sm2_privkey_t **out_key)
;

/*
 Sign `msg` with the SM2 private key using the supplied
 `signer_id` (or [`DEFAULT_SIGNER_ID`] = `"1234567812345678"` if
 `signer_id_len == 0`). Output is DER-encoded
 `SEQUENCE { r, s }`. RNG is sourced from `getrandom::SysRng`.
 */

int gmcrypto_sm2_sign(const gmcrypto_sm2_privkey_t *key,
                      const uint8_t *signer_id,
                      uintptr_t signer_id_len,
                      const uint8_t *msg,
                      uintptr_t msg_len,
                      uint8_t *out_der_sig,
                      uintptr_t out_capacity,
                      uintptr_t *out_actual_len)
;

/*
 Verify a DER-encoded `(r, s)` signature against `msg` using the
 SM2 public key and `signer_id`. Returns [`GMCRYPTO_OK`] on
 valid; [`GMCRYPTO_ERR`] on invalid or any error.
 */

int gmcrypto_sm2_verify(const gmcrypto_sm2_pubkey_t *key,
                        const uint8_t *signer_id,
                        uintptr_t signer_id_len,
                        const uint8_t *msg,
                        uintptr_t msg_len,
                        const uint8_t *der_sig,
                        uintptr_t der_sig_len)
;

/*
 SM2 public-key encrypt. Output is GM/T 0009-2012 DER. RNG from
 `getrandom::SysRng`.
 */

int gmcrypto_sm2_encrypt(const gmcrypto_sm2_pubkey_t *key,
                         const uint8_t *pt,
                         uintptr_t pt_len,
                         uint8_t *out_der_ct,
                         uintptr_t out_capacity,
                         uintptr_t *out_actual_len)
;

/*
 SM2 private-key decrypt of a GM/T 0009-2012 DER ciphertext.
 */

int gmcrypto_sm2_decrypt(const gmcrypto_sm2_privkey_t *key,
                         const uint8_t *der_ct,
                         uintptr_t der_ct_len,
                         uint8_t *out_pt,
                         uintptr_t out_capacity,
                         uintptr_t *out_actual_len)
;

#endif  /* GMCRYPTO_H_ */
