5.2 PKCS#11核心接口实现:从代码到理解
初始化与清理
C_Initialize:
CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
{
(void)pInitArgs; // 简化:忽略初始化参数
// 检查是否已初始化
if (g_ctx.initialized) {
return CKR_GENERAL_ERROR;
}
// 清零全局上下文
memset(&g_ctx, 0, sizeof(g_ctx));
// 设置初始化状态
g_ctx.initialized = CK_TRUE;
g_ctx.next_session_handle = 1; // 句柄从1开始
g_ctx.next_key_handle = 1;
printf("[hsm-lite] Initialized (version %s)\n", HSM_LITE_VERSION);
return CKR_OK;
}
实现要点:
C_Initialize要点:
1. 防止重复初始化
检查g_ctx.initialized状态
2. 初始化全局上下文
memset清零所有状态
3. 句柄起始值
从1开始(0保留为无效)
4. 打印日志
方便调试和追踪
C_Finalize:
CK_RV C_Finalize(CK_VOID_PTR pReserved)
{
(void)pReserved;
// 检查是否已初始化
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 清理状态
g_ctx.initialized = CK_FALSE;
printf("[hsm-lite] Finalized\n");
return CKR_OK;
}
Slot管理
C_GetSlotList:
CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
CK_ULONG_PTR pulCount)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 检查参数
if (!pulCount) {
return CKR_ARGUMENTS_BAD;
}
// hsm-lite只有一个Slot
*pulCount = 1;
// 如果提供了数组,填充Slot ID
if (pSlotList) {
pSlotList[0] = 0; // Slot ID = 0
}
return CKR_OK;
}
单Slot设计:
单Slot设计原因:
简化目的:
├── 教学导向,不需要多Slot
├── 真实HSM可能有多个Slot
├── SoftHSM2支持多Token
└── hsm-lite简化为单Slot
实际场景:
├── Slot 0 → 唯一的Token
├── 无物理插槽概念
└── 无可移除设备支持
Session管理
C_OpenSession:
CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags,
CK_SESSION_HANDLE_PTR phSession)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 验证Slot ID
if (slotID != 0) {
return CKR_SLOT_ID_INVALID;
}
// 验证参数
if (!phSession) {
return CKR_ARGUMENTS_BAD;
}
// 检查Session数量限制
if (g_ctx.session_count >= HSM_MAX_SESSIONS) {
return CKR_GENERAL_ERROR;
}
// 查找空闲Session槽位
for (CK_ULONG i = 0; i < HSM_MAX_SESSIONS; i++) {
if (!g_ctx.sessions[i].in_use) {
// 初始化Session
g_ctx.sessions[i].in_use = CK_TRUE;
g_ctx.sessions[i].handle = g_ctx.next_session_handle++;
g_ctx.sessions[i].slot_id = slotID;
g_ctx.sessions[i].is_rw = (flags & CKF_RW_SESSION) ? CK_TRUE : CK_FALSE;
g_ctx.sessions[i].encrypt_init = CK_FALSE;
g_ctx.sessions[i].decrypt_init = CK_FALSE;
g_ctx.session_count++;
// 返回Session句柄
*phSession = g_ctx.sessions[i].handle;
printf("[hsm-lite] OpenSession: handle=%lu\n", *phSession);
return CKR_OK;
}
}
return CKR_GENERAL_ERROR;
}
Session查找辅助函数:
static hsm_session_t *find_session(CK_SESSION_HANDLE hSession)
{
// 遍历Session数组,查找匹配句柄
for (CK_ULONG i = 0; i < HSM_MAX_SESSIONS; i++) {
if (g_ctx.sessions[i].in_use &&
g_ctx.sessions[i].handle == hSession) {
return &g_ctx.sessions[i];
}
}
return NULL; // 未找到
}
C_CloseSession:
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 查找Session
hsm_session_t *sess = find_session(hSession);
if (!sess) {
return CKR_SESSION_HANDLE_INVALID;
}
// 清理Session状态
sess->in_use = CK_FALSE;
g_ctx.session_count--;
printf("[hsm-lite] CloseSession: handle=%lu\n", hSession);
return CKR_OK;
}
密钥生成
C_GenerateKey:
CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phKey)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 验证Session
hsm_session_t *sess = find_session(hSession);
if (!sess) {
return CKR_SESSION_HANDLE_INVALID;
}
// 验证参数
if (!pMechanism || !phKey) {
return CKR_ARGUMENTS_BAD;
}
// 验证机制(只支持AES)
if (pMechanism->mechanism != CKM_AES_KEY_GEN) {
return CKR_MECHANISM_INVALID;
}
// 检查密钥数量限制
if (g_ctx.key_count >= HSM_MAX_OBJECTS) {
return CKR_GENERAL_ERROR;
}
// 查找空闲密钥槽位
for (CK_ULONG i = 0; i < HSM_MAX_OBJECTS; i++) {
if (!g_ctx.keys[i].in_use) {
// 初始化密钥对象
g_ctx.keys[i].in_use = CK_TRUE;
g_ctx.keys[i].handle = g_ctx.next_key_handle++;
g_ctx.keys[i].key_len = HSM_AES_KEY_SIZE; // 32字节
// 生成随机密钥值
CK_RV rv = get_random_bytes(g_ctx.keys[i].key, HSM_AES_KEY_SIZE);
if (rv != CKR_OK) {
g_ctx.keys[i].in_use = CK_FALSE;
return rv;
}
g_ctx.key_count++;
// 返回密钥句柄
*phKey = g_ctx.keys[i].handle;
printf("[hsm-lite] GenerateKey: handle=%lu (AES-256)\n", *phKey);
return CKR_OK;
}
}
return CKR_GENERAL_ERROR;
}
随机数生成辅助函数:
static CK_RV get_random_bytes(CK_BYTE_PTR buf, CK_ULONG len)
{
// 从/dev/urandom读取随机字节
int fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) {
return CKR_GENERAL_ERROR;
}
ssize_t ret = read(fd, buf, len);
close(fd);
return (ret == (ssize_t)len) ? CKR_OK : CKR_GENERAL_ERROR;
}
加密操作
C_EncryptInit:
CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 验证Session
hsm_session_t *sess = find_session(hSession);
if (!sess) {
return CKR_SESSION_HANDLE_INVALID;
}
// 验证密钥
hsm_key_t *key = find_key(hKey);
if (!key) {
return CKR_KEY_HANDLE_INVALID;
}
// 验证机制
if (pMechanism->mechanism != CKM_AES_ECB &&
pMechanism->mechanism != CKM_AES_CBC) {
return CKR_MECHANISM_INVALID;
}
// 设置加密操作状态
sess->active_mech = pMechanism->mechanism;
sess->active_key = hKey;
sess->encrypt_init = CK_TRUE;
printf("[hsm-lite] EncryptInit: mech=%s\n",
pMechanism->mechanism == CKM_AES_ECB ? "ECB" : "CBC");
return CKR_OK;
}
C_Encrypt:
CK_RV C_Encrypt(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pData, CK_ULONG ulDataLen,
CK_BYTE_PTR pEncrypted, CK_ULONG_PTR pulEncryptedLen)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 验证Session
hsm_session_t *sess = find_session(hSession);
if (!sess) {
return CKR_SESSION_HANDLE_INVALID;
}
// 验证加密已初始化
if (!sess->encrypt_init) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 获取密钥
hsm_key_t *key = find_key(sess->active_key);
if (!key) {
return CKR_KEY_HANDLE_INVALID;
}
// 验证参数
if (!pEncrypted || !pulEncryptedLen) {
return CKR_ARGUMENTS_BAD;
}
// 设置输出长度
*pulEncryptedLen = ulDataLen;
// 执行加密
CK_RV rv;
if (sess->active_mech == CKM_AES_ECB) {
rv = aes_encrypt_ecb(key->key, pData, ulDataLen, pEncrypted);
} else {
CK_BYTE iv[16] = {0}; // 简化:固定IV
rv = aes_encrypt_cbc(key->key, iv, pData, ulDataLen, pEncrypted);
}
printf("[hsm-lite] Encrypt: %lu bytes -> %lu bytes\n",
ulDataLen, *pulEncryptedLen);
return rv;
}
解密操作
C_DecryptInit:
CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 验证Session
hsm_session_t *sess = find_session(hSession);
if (!sess) {
return CKR_SESSION_HANDLE_INVALID;
}
// 验证密钥
hsm_key_t *key = find_key(hKey);
if (!key) {
return CKR_KEY_HANDLE_INVALID;
}
// 验证机制
if (pMechanism->mechanism != CKM_AES_ECB &&
pMechanism->mechanism != CKM_AES_CBC) {
return CKR_MECHANISM_INVALID;
}
// 设置解密操作状态
sess->active_mech = pMechanism->mechanism;
sess->active_key = hKey;
sess->decrypt_init = CK_TRUE;
printf("[hsm-lite] DecryptInit: mech=%s\n",
pMechanism->mechanism == CKM_AES_ECB ? "ECB" : "CBC");
return CKR_OK;
}
C_Decrypt:
CK_RV C_Decrypt(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncrypted, CK_ULONG ulEncryptedLen,
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 验证Session
hsm_session_t *sess = find_session(hSession);
if (!sess) {
return CKR_SESSION_HANDLE_INVALID;
}
// 验证解密已初始化
if (!sess->decrypt_init) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 获取密钥
hsm_key_t *key = find_key(sess->active_key);
if (!key) {
return CKR_KEY_HANDLE_INVALID;
}
// 验证参数
if (!pData || !pulDataLen) {
return CKR_ARGUMENTS_BAD;
}
// 设置输出长度
*pulDataLen = ulEncryptedLen;
// 执行解密
CK_RV rv;
if (sess->active_mech == CKM_AES_ECB) {
rv = aes_decrypt_ecb(key->key, pEncrypted, ulEncryptedLen, pData);
} else {
CK_BYTE iv[16] = {0};
rv = aes_decrypt_cbc(key->key, iv, pEncrypted, ulEncryptedLen, pData);
}
printf("[hsm-lite] Decrypt: %lu bytes -> %lu bytes\n",
ulEncryptedLen, *pulDataLen);
return rv;
}
Object管理
C_CreateObject:
CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phObject)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 验证Session
hsm_session_t *sess = find_session(hSession);
if (!sess) {
return CKR_SESSION_HANDLE_INVALID;
}
// 验证参数
if (!pTemplate || !phObject || ulCount == 0) {
return CKR_ARGUMENTS_BAD;
}
// 解析属性模板
CK_OBJECT_CLASS class = CKO_SECRET_KEY;
CK_KEY_TYPE key_type = CKK_AES;
CK_ULONG value_len = HSM_AES_KEY_SIZE;
CK_BYTE_PTR value = NULL;
for (CK_ULONG i = 0; i < ulCount; i++) {
switch (pTemplate[i].type) {
case CKA_CLASS:
class = *((CK_OBJECT_CLASS *)pTemplate[i].pValue);
break;
case CKA_KEY_TYPE:
key_type = *((CK_KEY_TYPE *)pTemplate[i].pValue);
break;
case CKA_VALUE:
value = (CK_BYTE_PTR)pTemplate[i].pValue;
value_len = pTemplate[i].ulValueLen;
break;
}
}
// 验证对象类型
if (class != CKO_SECRET_KEY || key_type != CKK_AES) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
// 创建密钥对象
// ...(查找空闲槽位,复制密钥值)
printf("[hsm-lite] CreateObject: handle=%lu\n", *phObject);
return CKR_OK;
}
C_GetAttributeValue:
CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 验证Session和对象
hsm_session_t *sess = find_session(hSession);
if (!sess) {
return CKR_SESSION_HANDLE_INVALID;
}
hsm_key_t *key = find_key(hObject);
if (!key) {
return CKR_OBJECT_HANDLE_INVALID;
}
// 填充属性值
for (CK_ULONG i = 0; i < ulCount; i++) {
switch (pTemplate[i].type) {
case CKA_CLASS:
if (pTemplate[i].pValue) {
*((CK_OBJECT_CLASS *)pTemplate[i].pValue) = CKO_SECRET_KEY;
}
pTemplate[i].ulValueLen = sizeof(CK_OBJECT_CLASS);
break;
case CKA_KEY_TYPE:
if (pTemplate[i].pValue) {
*((CK_KEY_TYPE *)pTemplate[i].pValue) = CKK_AES;
}
pTemplate[i].ulValueLen = sizeof(CK_KEY_TYPE);
break;
case CKA_VALUE_LEN:
if (pTemplate[i].pValue) {
*((CK_ULONG *)pTemplate[i].pValue) = key->key_len;
}
pTemplate[i].ulValueLen = sizeof(CK_ULONG);
break;
case CKA_VALUE:
if (pTemplate[i].pValue) {
memcpy(pTemplate[i].pValue, key->key, key->key_len);
pTemplate[i].ulValueLen = key->key_len;
} else {
pTemplate[i].ulValueLen = key->key_len; // 返回长度
}
break;
default:
pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION;
break;
}
}
return CKR_OK;
}
随机数生成
C_GenerateRandom:
CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
{
// 检查初始化状态
if (!g_ctx.initialized) {
return CKR_FUNCTION_NOT_INITIALIZED;
}
// 验证Session
hsm_session_t *sess = find_session(hSession);
if (!sess) {
return CKR_SESSION_HANDLE_INVALID;
}
// 验证参数
if (!pRandomData) {
return CKR_ARGUMENTS_BAD;
}
// 从系统熵源获取随机数
CK_RV rv = get_random_bytes(pRandomData, ulRandomLen);
printf("[hsm-lite] GenerateRandom: %lu bytes\n", ulRandomLen);
return rv;
}
实现流程总结
hsm-lite函数调用流程:
应用程序调用
│
│ C_Initialize()
├── 检查是否已初始化
├── 清零全局上下文
├── 设置句柄起始值
▼
初始化完成
│
│ C_GetSlotList()
├── 返回单Slot
▼
获取Slot
│
│ C_OpenSession()
├── 查找空闲Session槽位
├── 分配句柄
├── 初始化Session状态
▼
Session创建
│
│ C_GenerateKey()
├── 验证机制(AES)
├── 查找空闲密钥槽位
├── 从/dev/urandom获取随机字节
├── 分配密钥句柄
▼
密钥创建
│
│ C_EncryptInit()
├── 验证机制(ECB/CBC)
├── 设置Session加密状态
▼
加密初始化
│
│ C_Encrypt()
├── 获取Session的活跃密钥
├── 执行简化AES(XOR)
▼
加密完成
│
│ C_Decrypt()
├── 类似Encrypt
▼
解密完成
│
│ C_CloseSession()
│ C_Finalize()
▼
清理完成
本篇小结
hsm-lite的核心实现约615行代码:
初始化管理:
- C_Initialize:清零全局上下文,设置句柄起始值
- C_Finalize:清理初始化状态
Slot管理:
- C_GetSlotList:返回单Slot(简化设计)
Session管理:
- C_OpenSession:查找空闲槽位,分配句柄
- C_CloseSession:清理Session状态
- find_session:辅助查找函数
密钥操作:
- C_GenerateKey:从/dev/urandom生成随机密钥
- find_key:辅助查找密钥
加密解密:
- C_EncryptInit/C_DecryptInit:设置操作状态
- C_Encrypt/C_Decrypt:执行XOR简化加密
Object管理:
- C_CreateObject:从属性模板创建对象
- C_GetAttributeValue:返回对象属性
随机数:
- C_GenerateRandom:从系统熵源获取
下一节,我们将分析安全存储与密钥管理——密钥如何存储、查找、销毁。
【下集预告】
密钥如何存储?
如何通过Handle查找密钥?
密钥如何销毁?
下一节,安全存储与密钥管理。