Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

5.4 测试程序与编译:验证hsm-lite

测试程序设计

hsm-lite的测试程序hsm_test.c包含4个测试案例:

测试程序结构:

hsm_test.c(约230行)
│
├── test_basic_flow()       基础流程测试
│   ├── C_Initialize
│   ├── C_GetSlotList
│   ├── C_OpenSession
│   ├── C_CloseSession
│   └── C_Finalize
│
├── test_key_generation()   密钥生成测试
│   ├── C_GenerateKey
│   ├── C_GetAttributeValue
│   └── C_DestroyObject
│
├── test_encrypt_decrypt()  加密解密测试
│   ├── C_EncryptInit
│   ├── C_Encrypt
│   ├── C_DecryptInit
│   ├── C_Decrypt
│   └── 验证加密解密一致性
│
└── test_random()           随机数测试
    └── C_GenerateRandom

基础流程测试

static int test_basic_flow(void)
{
    CK_RV rv;
    CK_SESSION_HANDLE hSession;
    CK_SLOT_ID slots[1];
    CK_ULONG slot_count;
    
    printf("\n=== Test 1: Basic Flow ===\n\n");
    
    /* 1. 初始化 */
    rv = C_Initialize(NULL);
    if (rv != CKR_OK) {
        printf("FAIL: C_Initialize returned %lu\n", rv);
        return -1;
    }
    printf("PASS: C_Initialize\n");
    
    /* 2. 获取Slot列表 */
    rv = C_GetSlotList(CK_TRUE, slots, &slot_count);
    if (rv != CKR_OK || slot_count != 1) {
        printf("FAIL: C_GetSlotList returned %lu, count=%lu\n", rv, slot_count);
        return -1;
    }
    printf("PASS: C_GetSlotList (count=%lu)\n", slot_count);
    
    /* 3. 打开Session */
    rv = C_OpenSession(slots[0], CKF_SERIAL_SESSION | CKF_RW_SESSION, &hSession);
    if (rv != CKR_OK) {
        printf("FAIL: C_OpenSession returned %lu\n", rv);
        return -1;
    }
    printf("PASS: C_OpenSession (handle=%lu)\n", hSession);
    
    /* 4. 关闭Session */
    rv = C_CloseSession(hSession);
    if (rv != CKR_OK) {
        printf("FAIL: C_CloseSession returned %lu\n", rv);
        return -1;
    }
    printf("PASS: C_CloseSession\n");
    
    /* 5. 清理 */
    rv = C_Finalize(NULL);
    if (rv != CKR_OK) {
        printf("FAIL: C_Finalize returned %lu\n", rv);
        return -1;
    }
    printf("PASS: C_Finalize\n");
    
    return 0;
}

密钥生成测试

static int test_key_generation(void)
{
    CK_RV rv;
    CK_SESSION_HANDLE hSession;
    CK_OBJECT_HANDLE hKey;
    CK_MECHANISM mechanism = {CKM_AES_KEY_GEN, NULL, 0};
    CK_BYTE key_value[32];
    CK_ULONG key_len;
    
    printf("\n=== Test 2: Key Generation ===\n\n");
    
    rv = C_Initialize(NULL);
    rv = C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, &hSession);
    
    /* 1. 生成AES密钥 */
    rv = C_GenerateKey(hSession, &mechanism, NULL, 0, &hKey);
    if (rv != CKR_OK) {
        printf("FAIL: C_GenerateKey returned %lu\n", rv);
        return -1;
    }
    printf("PASS: C_GenerateKey (handle=%lu)\n", hKey);
    
    /* 2. 获取密钥属性 */
    CK_ATTRIBUTE template[] = {
        {CKA_VALUE, key_value, sizeof(key_value)},
        {CKA_VALUE_LEN, &key_len, sizeof(key_len)}
    };
    
    rv = C_GetAttributeValue(hSession, hKey, template, 2);
    print_bytes("Key value", key_value, key_len);
    printf("PASS: C_GetAttributeValue (len=%lu)\n", key_len);
    
    /* 3. 销毁密钥 */
    rv = C_DestroyObject(hSession, hKey);
    printf("PASS: C_DestroyObject\n");
    
    C_CloseSession(hSession);
    C_Finalize(NULL);
    
    return 0;
}

加密解密测试

static int test_encrypt_decrypt(void)
{
    CK_RV rv;
    CK_SESSION_HANDLE hSession;
    CK_OBJECT_HANDLE hKey;
    CK_MECHANISM key_mech = {CKM_AES_KEY_GEN, NULL, 0};
    CK_MECHANISM enc_mech = {CKM_AES_ECB, NULL, 0};
    
    CK_BYTE plaintext[32] = "Hello, hsm-lite!";
    CK_ULONG pt_len = 17;
    CK_BYTE ciphertext[32];
    CK_ULONG ct_len;
    CK_BYTE decrypted[32];
    CK_ULONG dec_len;
    
    printf("\n=== Test 3: Encrypt/Decrypt ===\n\n");
    
    rv = C_Initialize(NULL);
    rv = C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, &hSession);
    rv = C_GenerateKey(hSession, &key_mech, NULL, 0, &hKey);
    
    print_bytes("Plaintext", plaintext, pt_len);
    
    /* 1. 加密 */
    ct_len = sizeof(ciphertext);
    rv = C_EncryptInit(hSession, &enc_mech, hKey);
    rv = C_Encrypt(hSession, plaintext, pt_len, ciphertext, &ct_len);
    
    print_bytes("Ciphertext", ciphertext, ct_len);
    printf("PASS: Encrypt (%lu -> %lu bytes)\n", pt_len, ct_len);
    
    /* 2. 解密 */
    dec_len = sizeof(decrypted);
    rv = C_DecryptInit(hSession, &enc_mech, hKey);
    rv = C_Decrypt(hSession, ciphertext, ct_len, decrypted, &dec_len);
    
    print_bytes("Decrypted", decrypted, dec_len);
    printf("PASS: Decrypt (%lu -> %lu bytes)\n", ct_len, dec_len);
    
    /* 3. 验证一致性 */
    if (memcmp(plaintext, decrypted, pt_len) == 0) {
        printf("PASS: Plaintext matches decrypted text\n");
    } else {
        printf("FAIL: Plaintext does NOT match decrypted text\n");
        return -1;
    }
    
    C_DestroyObject(hSession, hKey);
    C_CloseSession(hSession);
    C_Finalize(NULL);
    
    return 0;
}

测试逻辑

加密解密测试流程:

 plaintext = "Hello, hsm-lite!"
         │
         │ C_EncryptInit + C_Encrypt
         ▼
 ciphertext(加密后)
         │
         │ C_DecryptInit + C_Decrypt
         ▼
 decrypted(解密后)
         │
         │ memcmp(plaintext, decrypted)
         ▼
 验证:plaintext == decrypted ?

随机数测试

static int test_random(void)
{
    CK_RV rv;
    CK_SESSION_HANDLE hSession;
    CK_BYTE random[32];
    
    printf("\n=== Test 4: Random Generation ===\n\n");
    
    rv = C_Initialize(NULL);
    rv = C_OpenSession(0, CKF_SERIAL_SESSION, &hSession);
    
    rv = C_GenerateRandom(hSession, random, sizeof(random));
    print_bytes("Random", random, sizeof(random));
    printf("PASS: C_GenerateRandom\n");
    
    C_CloseSession(hSession);
    C_Finalize(NULL);
    
    return 0;
}

辅助函数

static void print_bytes(const char *label, CK_BYTE_PTR data, CK_ULONG len)
{
    printf("%s: ", label);
    for (CK_ULONG i = 0; i < len && i < 16; i++) {
        printf("%02x", data[i]);
    }
    if (len > 16) {
        printf("... (%lu bytes)", len);
    }
    printf("\n");
}

主测试入口

int main(int argc, char *argv[])
{
    (void)argc;
    (void)argv;
    
    printf("========================================\n");
    printf("  hsm-lite Test Suite (version %s)\n", HSM_LITE_VERSION);
    printf("========================================\n");
    
    int failed = 0;
    
    // 运行所有测试
    failed += test_basic_flow();
    failed += test_key_generation();
    failed += test_encrypt_decrypt();
    failed += test_random();
    
    printf("\n========================================\n");
    if (failed == 0) {
        printf("  ALL TESTS PASSED\n");
    } else {
        printf("  %d TESTS FAILED\n", failed);
    }
    printf("========================================\n");
    
    return failed;
}

编译配置

Makefile

# ==================== 编译器配置 ====================

# x86编译器(默认)
CC = gcc

# ARM架构编译器
CC_ARM64 = aarch64-linux-gnu-gcc
CC_ARM32 = arm-linux-gnueabihf-gcc  # 硬浮点版本

# ==================== 编译选项 ====================

CFLAGS = -Wall -Wextra -O2 -std=gnu11
LDFLAGS = 

# ==================== x86编译目标(默认) ====================

all: hsm_test

hsm_test: hsm_test.c hsm_lite.c
	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)

# ==================== ARM64编译目标 ====================

arm64: hsm_test_arm64

hsm_test_arm64: hsm_test.c hsm_lite.c
	$(CC_ARM64) $(CFLAGS_ARM64) -o $@ $^ $(LDFLAGS_ARM64)

# ==================== ARM32编译目标 ====================

arm32: hsm_test_arm32

hsm_test_arm32: hsm_test.c hsm_lite.c
	$(CC_ARM32) $(CFLAGS_ARM32) -o $@ $^ $(LDFLAGS_ARM32)

# ==================== 清理目标 ====================

clean:
	rm -f hsm_test *.o

clean-arm64:
	rm -f hsm_test_arm64 *.o

clean-arm32:
	rm -f hsm_test_arm32 *.o

clean-all: clean clean-arm64 clean-arm32

# ==================== 辅助目标 ====================

# 编译所有架构版本
all-arch: all arm64 arm32

.PHONY: all arm64 arm32 clean clean-arm64 clean-arm32 clean-all all-arch

编译与运行

编译命令

# 编译x86版本(默认)
make

# 编译ARM64版本
make arm64

# 编译ARM32版本
make arm32

# 编译所有架构
make all-arch

# 清理
make clean

运行测试

./hsm_test

预期输出

========================================
  hsm-lite Test Suite (version 1.0.0)
========================================

=== Test 1: Basic Flow ===

[hsm-lite] Initialized (version 1.0.0)
PASS: C_Initialize
PASS: C_GetSlotList (count=1)
[hsm-lite] OpenSession: handle=1
PASS: C_OpenSession (handle=1)
[hsm-lite] CloseSession: handle=1
PASS: C_CloseSession
[hsm-lite] Finalized
PASS: C_Finalize

=== Test 2: Key Generation ===

[hsm-lite] Initialized (version 1.0.0)
[hsm-lite] OpenSession: handle=1
[hsm-lite] GenerateKey: handle=1 (AES-256)
PASS: C_GenerateKey (handle=1)
Key value: a3f5b8c1d2e4f6a7...
PASS: C_GetAttributeValue (len=32)
[hsm-lite] DestroyObject: handle=1
PASS: C_DestroyObject

=== Test 3: Encrypt/Decrypt ===

[hsm-lite] Initialized (version 1.0.0)
[hsm-lite] OpenSession: handle=1
[hsm-lite] GenerateKey: handle=1 (AES-256)
Plaintext: 48656c6c6f2c2068
[hsm-lite] EncryptInit: mech=ECB
[hsm-lite] Encrypt: 17 bytes -> 17 bytes
Ciphertext: 1b3d5f7a9c1e2f4...
PASS: Encrypt (17 -> 17 bytes)
[hsm-lite] DecryptInit: mech=ECB
[hsm-lite] Decrypt: 17 bytes -> 17 bytes
Decrypted: 48656c6c6f2c2068
PASS: Decrypt (17 -> 17 bytes)
PASS: Plaintext matches decrypted text

=== Test 4: Random Generation ===

[hsm-lite] Initialized (version 1.0.0)
[hsm-lite] OpenSession: handle=1
[hsm-lite] GenerateRandom: 32 bytes
Random: 7a3c9f2e1b5d8a4...
PASS: C_GenerateRandom

========================================
  ALL TESTS PASSED
========================================

多架构编译说明

多架构支持:

架构:
├── 本机    原生架构(make all / make)
├── arm32  32位ARM Linux(Cortex-A,arm-linux-gnueabihf-gcc)
├── arm64  64位ARM Linux(Cortex-A,aarch64-linux-gnu-gcc)
└── 注意:arm32/arm64为交叉编译目标,需安装对应的交叉工具链

交叉编译需求:
├── arm32需要 arm-linux-gnueabihf-gcc(硬浮点)
├── arm64需要 aarch64-linux-gnu-gcc
├── 安装方法:
│   ├── Debian/Ubuntu:
│   │   sudo apt install gcc-arm-linux-gnueabihf
│   │   sudo apt install gcc-aarch64-linux-gnu
│   └── Fedora:
│       sudo dnf install arm-linux-gnueabihf-gcc
│       sudo dnf install aarch64-linux-gnu-gcc

一个类比:课程实验

课程实验类比:

hsm-lite测试(课程实验)
│
├── 测试目的
│   ├── 验证理论(PKCS#11概念)
│   ├── 检验实现(代码正确性)
│   ├── 理解流程(操作顺序)
│   └── 发现问题(错误处理)
│
├── 测试设计
│   ├── 基础流程:初始化→清理
│   ├── 密钥生成:生成→读取→销毁
│   ├── 加密解密:加密→解密→验证
│   └── 随机数:生成随机字节
│
├── 测试执行
│   ├── 每个测试独立运行
│   ├── 从初始化开始
│   ├── 打印每个步骤
│   └── 检查返回值
│
├── 结果判断
│   ├── PASS:返回CKR_OK
│   ├── FAIL:返回错误码
│   ├── 统计失败数
│   └── 最终汇总
│
└── 学习价值
    ├── 理解PKCS#11使用流程
    ├── 验证接口正确性
    ├── 学习测试设计方法
    └── 可扩展更多测试

本篇小结

hsm-lite的测试与编译:

测试程序

  • 4个测试案例
  • 约230行代码
  • 每个测试独立完整

测试案例

  • test_basic_flow:初始化流程
  • test_key_generation:密钥生成与销毁
  • test_encrypt_decrypt:加密解密验证
  • test_random:随机数生成

辅助函数

  • print_bytes:打印字节序列

编译配置

  • Makefile多架构支持
  • 本机/arm32/arm64三种编译目标
  • 交叉编译工具链需求

运行方法

  • make编译
  • ./hsm_test运行
  • 查看PASS/FAIL结果

预期结果

  • ALL TESTS PASSED
  • 每个步骤打印日志
  • 加密解密一致性验证

hsm-lite完成了从理论到实践的闭环——约600行代码实现PKCS#11核心功能,可编译运行,测试验证。

下一章,我们将进入真实项目集成——用现成SDK连接真实HSM芯片。

【第五章总结】

第五章结束了。我们亲手实现了PKCS#11核心功能:

  • 项目定位:教学级实现,约600行代码
  • 核心接口:初始化、Slot/Session管理、密钥生成、加密解密
  • 安全存储:密钥数组、Handle分配、属性管理
  • 测试验证:完整测试程序,多架构编译

“自己实现“完成了知识内化。接下来进入真实项目集成。

第六章,HSM集成实战。