AES-GCM和SM4-GCM工作原理及数据加解密验证方案详解

AES-GCM和SM4-GCM工作原理及数据加解密验证方案详解

下面分三部分给出:

  1. AES-GCM / SM4-GCM 原理梳理
  2. 基于 OpenSSL 的 C 语言 Reference Model (可编译成 DPI-C 动态库)
  3. SystemVerilog DPI 调用示例

1. AES-GCM 与 SM4-GCM 工作原理

1.1 GCM 模式总体架构

       GCM (Galois/Counter Mode)是一种同时提供加密(Confidentiality)和认证(Authenticity)的分组密码工作模式。它用 CTR 模式做流加密,用 GHASH 做消息认证。

  1. 密钥 K
  2. 分组加密
    • 生成哈希子键 H = E_K(0^128)
    • 若 IV 长度=96 bit,则初始计数器
      J₀ = IV ∥ 0x00000001
      否则
      J₀ = GHASH_H(pad(IV))
  3. CTR 加密
    • 对第 i 个块:
      CTR_i = inc32(J₀, i)
      S_i = E_K(CTR_i)
      C_i = P_i ⊕ S_i
  4. GHASH 认证
    • 定义 GHASH_H(X) = ∑ X_i·H^(n−i+1) (GHASH 是在 GF(2^128) 上的多项式乘加)
    • 输入到 GHASH:AAD、填充、密文、填充、len(AAD)||len(C)
    • 认证标签 T = E_K(J₀) ⊕ GHASH_H(AAD||C)

1.2 AES-GCM vs SM4-GCM

  • BlockCipher
    • AES-GCM:E_K = AES 加密
    • SM4-GCM:E_K = SM4 加密
  • 其余流程完全相同(CTR 计数器、GHASH 认证多项式不变)

2. Reference Model:C/C++ + OpenSSL

       下面给出一个简单的 reference model,使用 OpenSSL EVP API 实现 AES-GCM 和 SM4-GCM 的加解密。编译成动态库后,可由 SystemVerilog DPI-C 调用。

/* ref_gcm.c */
#include 
#include 
#include 
#include 

/*
 * Encrypt (or decrypt) in GCM mode
 * - cipher: EVP_aes_128_gcm(), EVP_aes_256_gcm(), EVP_sm4_gcm() (OpenSSL1.1.1+)
 * - is_enc: 1=encrypt, 0=decrypt
 * - tag_len: 推荐16
 * 返回 0=OK, <0=ERR
 */
static int gcm_crypt(const EVP_CIPHER *cipher,
                     const uint8_t *key, int key_len,
                     const uint8_t *iv,  int iv_len,
                     const uint8_t *aad, int aad_len,
                     const uint8_t *in,  int in_len,
                     uint8_t *out,
                     uint8_t *tag,      int tag_len,
                     int is_enc)
{
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    int len, ret = -1;

    if(!ctx) return -1;
    if(1 != EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, is_enc)) goto end;
    // IV 长度
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL);
    // Key & IV
    if(1 != EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, is_enc)) goto end;
    // AAD
    if(aad && aad_len>0){
        if(1 != EVP_CipherUpdate(ctx, NULL, &len, aad, aad_len)) goto end;
    }
    // 数据
    if(in && in_len>0){
        if(1 != EVP_CipherUpdate(ctx, out, &len, in, in_len)) goto end;
    }
    // Encrypt Final / Get plaintext
    if(1 != EVP_CipherFinal_ex(ctx, out+len, &len)) goto end;
    // Tag
    if(is_enc){
        if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tag)) goto end;
    } else {
        // 验证 tag
        if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag_len, tag)) goto end;
    }
    ret = 0;
end:
    EVP_CIPHER_CTX_free(ctx);
    return ret;
}

// AES-128-GCM
int aes128_gcm_encrypt(const uint8_t *key, const uint8_t *iv, int iv_len,
                       const uint8_t *aad, int aad_len,
                       const uint8_t *pt,  int pt_len,
                       uint8_t *ct,       uint8_t *tag)
{
    return gcm_crypt(EVP_aes_128_gcm(), key, 16, iv, iv_len, aad, aad_len, pt, pt_len, ct, tag, 16, 1);
}
int aes128_gcm_decrypt(const uint8_t *key, const uint8_t *iv, int iv_len,
                       const uint8_t *aad, int aad_len,
                       const uint8_t *ct,  int ct_len,
                       const uint8_t *tag,
                       uint8_t *pt)
{
    return gcm_crypt(EVP_aes_128_gcm(), key, 16, iv, iv_len, aad, aad_len, ct, ct_len, pt, (uint8_t*)tag, 16, 0);
}

// SM4-GCM (OpenSSL 1.1.1+ 支持)
int sm4_gcm_encrypt(const uint8_t *key, const uint8_t *iv, int iv_len,
                    const uint8_t *aad, int aad_len,
                    const uint8_t *pt, int pt_len,
                    uint8_t *ct, uint8_t *tag)
{
    return gcm_crypt(EVP_sm4_gcm(), key, 16, iv, iv_len, aad, aad_len, 

你可能感兴趣的:(PCIe/UCIe学习笔记,国密算法,数据加解密,PCIe加密传输)