第25课:AES-GCM 引擎

阶段五实战项目 — AES-GCM 是 TLS 1.3 的核心 AEAD 方案。它结合 AES-CTR 加密和 GHASH 认证,提供同时保密和完整性保护。

1. AES-GCM 概述

GCM(Galois/Counter Mode)提供认证加密:

密文 = AES-CTR(明文, IV, Key)
认证标签 = GHASH(AAD, 密文, H)

其中 H = AES_K(0¹²⁸) 是哈希子密钥。

2. GHASH 运算

GHASH 在 GF(2¹²⁸) 上运算,使用多项式 x¹²⁸ + x⁷ + x² + x + 1:

Xᵢ = (Xᵢ₋₁ ⊕ Cᵢ) · H
✅Verilator验证通过
// ghash.v - GHASH 乘法模块
module ghash_mul (
    input  wire [127:0] x,
    input  wire [127:0] h,
    output wire [127:0] y
);

    // GF(2^128) 乘法,多项式 x^128 + x^7 + x^2 + x + 1
    // 使用移位+条件约减法
    reg [255:0] product;
    reg [127:0] result;
    integer i;

    // 简化实现:先做 128 位乘法,再模约减
    always @(*) begin
        product = 256'h0;
        for (i = 0; i < 128; i = i + 1) begin
            if (x[i])
                product = product ^ (h << i);
        end

        // 模约减:x^128 = x^7 + x^2 + x + 1
        result = product[127:0];
        for (i = 255; i >= 128; i = i - 1) begin
            if (product[i]) begin
                result[i-128]   = result[i-128] ^ 1'b1;
                result[i-128+7] = result[i-128+7] ^ 1'b1;
                result[i-128+2] = result[i-128+2] ^ 1'b1;
                result[i-128+1] = result[i-128+1] ^ 1'b1;
            end
        end
    end

    assign y = result;

endmodule
✅Verilator验证通过
// aes_gcm.v - AES-GCM 引擎(简化版)
module aes_gcm (
    input  wire         clk,
    input  wire         rst_n,
    input  wire         start,
    input  wire [127:0] key,
    input  wire [95:0]  iv,          // 96位初始向量
    input  wire [127:0] plaintext,
    input  wire [127:0] aad,         // 附加认证数据
    input  wire         last_block,
    output reg  [127:0] ciphertext,
    output reg  [127:0] auth_tag,
    output reg          tag_valid
);

    // 状态机
    localparam S_IDLE=0, S_INIT=1, S_ENCRYPT=2, S_HASH=3, S_TAG=4;
    reg [2:0] state;

    // 计数器
    reg [31:0] ctr;

    // GHASH 累积器
    reg [127:0] ghash_state;
    reg [127:0] hash_key;  // H = AES_K(0)

    // AES 加密实例(简化)
    reg         aes_start;
    reg  [127:0] aes_pt, aes_key;
    wire [127:0] aes_ct;
    wire        aes_valid;

    aes128_enc u_aes (
        .clk(clk), .rst_n(rst_n), .start(aes_start),
        .plaintext(aes_pt), .key(aes_key),
        .ciphertext(aes_ct), .valid(aes_valid), .busy()
    );

    // GHASH 乘法实例
    wire [127:0] ghash_out;
    ghash_mul u_ghash (.x(ghash_state), .h(hash_key), .y(ghash_out));

    // 密钥流
    reg [127:0] key_stream;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            state <= S_IDLE; ctr <= 0;
            ghash_state <= 0; hash_key <= 0;
            ciphertext <= 0; auth_tag <= 0; tag_valid <= 0;
            aes_start <= 0; key_stream <= 0;
        end else begin
            aes_start <= 0;
            tag_valid <= 0;

            case (state)
                S_IDLE: if (start) begin
                    // 计算 H = AES_K(0^128)
                    aes_pt <= 128'h0; aes_key <= key;
                    aes_start <= 1;
                    ctr <= 32'd1;  // 计数器从1开始
                    state <= S_INIT;
                end
                S_INIT: if (aes_valid) begin
                    hash_key <= aes_ct;  // H
                    // 计算初始密钥流
                    aes_pt <= {iv, 32'd1};  // J0
                    aes_key <= key;
                    aes_start <= 1;
                    ghash_state <= 0;
                    state <= S_ENCRYPT;
                end
                S_ENCRYPT: if (aes_valid) begin
                    key_stream <= aes_ct;
                    ciphertext <= plaintext ^ aes_ct;

                    // GHASH: 处理密文块
                    ghash_state <= ghash_out ^ ciphertext;

                    if (last_block) begin
                        // 处理 AAD 的 GHASH(简化:假设只有一块 AAD)
                        state <= S_HASH;
                    end else begin
                        ctr <= ctr + 1;
                        aes_pt <= {iv, ctr + 1};
                        aes_key <= key;
                        aes_start <= 1;
                    end
                end
                S_HASH: begin
                    // 包含长度信息的最终 GHASH
                    ghash_state <= ghash_out ^ {64'h0, 64'd128};  // 简化
                    state <= S_TAG;
                end
                S_TAG: begin
                    // 认证标签 = GHASH ⊕ AES_K(J0)
                    auth_tag <= ghash_out ^ key_stream;
                    tag_valid <= 1;
                    state <= S_IDLE;
                end
            endcase
        end
    end

endmodule

1. 验证 AES-GCM 的 NIST 测试向量(Test Case 1-4)。

2. 优化 GF(2¹²⁸) 乘法:实现 Karatsuba 分解,减少关键路径延迟。

3. 实现完整的 AES-GCM 解密和验证:解密后重新计算标签并比较。

4. 安全分析:如果 IV 重复使用,AES-GCM 的安全性如何被破坏?

🏆 成就解锁:AEAD 先锋

你已实现 AES-GCM 认证加密引擎,掌握 GHASH 和 GF(2¹²⁸) 乘法。AES-GCM 是现代网络安全的核心协议!

获得徽章:🔐 AEAD_PIONEER

💡 扩展阅读与参考资源

🔧 实践环境搭建

推荐使用以下工具链进行课程实践:

# 安装 Verilator
sudo apt install verilator

# 安装 Icarus Verilog(可选)
sudo apt install iverilog

# 安装 GTKWave(波形查看器)
sudo apt install gtkwave

# 验证安装
verilator --lint-only --version
iverilog -V

📊 性能指标对比

密码学硬件实现的关键性能指标:

这些指标之间通常存在 trade-off,设计时需根据应用场景权衡。

📚 本课知识图谱

本课涉及的核心概念和技术关系:

💡 调试技巧

Verilog 仿真调试的常用方法:

// 调试示例
initial begin
    $dumpfile("sim.vcd");
    $dumpvars(0, uut);
end

// 断言验证
assert property (@(posedge clk) valid |-> data !== 'x)
    else $error("Invalid data when valid!");

🔧 Verilator 编译仿真完整流程

# 1. 语法检查
verilator --lint-only module.v

# 2. 创建 C++ 测试主函数
cat > sim_main.cpp << 'EOF'
#include "Vmodule.h"
#include "verilated.h"
int main(int argc, char** argv) {
    Verilated::commandArgs(argc, argv);
    Vmodule* top = new Vmodule;
    top->clk = 0; top->rst_n = 0;
    top->eval();
    top->rst_n = 1;
    for (int i = 0; i < 100; i++) {
        top->clk = !top->clk;
        top->eval();
    }
    delete top;
    return 0;
}
EOF

# 3. 编译
verilator -cc module.v --exe sim_main.cpp
make -C obj_dir -f Vmodule.mk

# 4. 运行
./obj_dir/Vmodule

📖 推荐阅读

⚖️ 性能评估框架

密码硬件的性能评估维度:

指标单位说明
面积GE / LUT等效门数或查找表数量
频率MHz最大时钟频率
吞吐量Gbps每秒处理的数据量
延迟周期数从输入到输出的周期
能效pJ/bit每比特能耗
面积效率Gbps/GE单位面积吞吐量

不同应用场景对指标优先级不同:IoT 偏重面积和能效,服务器偏重吞吐量。

📚 本课知识图谱

本课涉及的核心概念和技术关系:

💡 调试技巧

Verilog 仿真调试的常用方法:

// 调试示例
initial begin
    $dumpfile("sim.vcd");
    $dumpvars(0, uut);
end

// 断言验证
assert property (@(posedge clk) valid |-> data !== 'x)
    else $error("Invalid data when valid!");

🔧 Verilator 编译仿真完整流程

# 1. 语法检查
verilator --lint-only module.v

# 2. 创建 C++ 测试主函数
cat > sim_main.cpp << 'EOF'
#include "Vmodule.h"
#include "verilated.h"
int main(int argc, char** argv) {
    Verilated::commandArgs(argc, argv);
    Vmodule* top = new Vmodule;
    top->clk = 0; top->rst_n = 0;
    top->eval();
    top->rst_n = 1;
    for (int i = 0; i < 100; i++) {
        top->clk = !top->clk;
        top->eval();
    }
    delete top;
    return 0;
}
EOF

# 3. 编译
verilator -cc module.v --exe sim_main.cpp
make -C obj_dir -f Vmodule.mk

# 4. 运行
./obj_dir/Vmodule

📖 推荐阅读

⚖️ 性能评估框架

密码硬件的性能评估维度:

指标单位说明
面积GE / LUT等效门数或查找表数量
频率MHz最大时钟频率
吞吐量Gbps每秒处理的数据量
延迟周期数从输入到输出的周期
能效pJ/bit每比特能耗
面积效率Gbps/GE单位面积吞吐量

不同应用场景对指标优先级不同:IoT 偏重面积和能效,服务器偏重吞吐量。