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.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查找密钥?

  • 密钥如何销毁?

下一节,安全存储与密钥管理。