#ifndef SM_H
#define SM_H
// 解决gmssl/gf128.h中包含stdio.h报错问题
#ifdef __cplusplus
#include <cstdio>
#else
#include <stdio.h>
#endif

typedef struct _IO_FILE FILE;  // 显式定义 FILE 类型

extern "C" {
    #include <gmssl/sm4.h>
    #include <gmssl/rand.h>
    #include <gmssl/sm3.h>
}
#include <iostream>

#define L_SM4_GCM_KEY_SIZE 16
#define L_SM4_GCM_TAG_SIZE 16
#define L_SM4_GCM_IV_SIZE 12
#define L_PCKS7_PAD_SIZE 16

class sm4{
    public:
    sm4(uint8_t *ckey);
    ~sm4();
    int encrypt_gcm(const uint8_t *in,const size_t inlen, uint8_t *&out, size_t &outlen);
    int decrypt_gcm(const uint8_t *in,const size_t inlen, uint8_t *&out, size_t &outlen);

    int encrypt_ecb(const uint8_t *in,const size_t inlen, uint8_t *&out, size_t &outlen);
    int decrypt_ecb(const uint8_t *in,const size_t inlen, uint8_t *&out, size_t &outlen);

    int encrypt_ecb_with_checksum(const uint8_t *in, const size_t inlen, uint8_t *&out, size_t &outlen);
    int decrypt_ecb_with_checksum(const uint8_t *in, const size_t inlen, uint8_t *&out, size_t &outlen);

    private:
    SM4_KEY encrypt_key;
    SM4_KEY decrypt_key;
    uint8_t* hmac_key;  // HMAC密钥
    size_t hmac_keylen; // HMAC密钥长度

    /**
     * 填充规则：
     * 若数据长度是块大小（16字节）的整数倍，添加一个完整填充块（16个0x10）
     * 若数据长度不足块大小，补充n个值为n的字节（如差3字节则填充0x03 0x03 0x03）
     * 填充示例：
     * 输入长度 14 字节 ➔ 填充 2 字节 0x02 0x02 (共 16 字节)
     * 输入长度 16 字节 ➔ 填充 16 字节 0x10（共 32 字节）
     */
    
    int pkcs7_pad(const uint8_t *in, const size_t inlen, uint8_t *&out, size_t &outlen);
    int pkcs7_unpad(const uint8_t *in, const size_t inlen, uint8_t *&out, size_t &outlen);
};



#endif