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

4.7 Handle管理模块:对象的“身份证发放“

一个问题:Handle怎么分配?

假设你刚刚理解了SessionManager的“窗口调度员“角色。

应用程序打开Session后,得到一个Session Handle(比如“3“)。

创建密钥后,得到一个Object Handle(比如“5“)。

你可能会想:

  • Handle的数字是怎么来的?
  • Handle能被理解吗?
  • Handle和内部对象怎么关联?

更深层的问题是:

Handle就像“身份证号“,身份证系统如何发放和管理?


“身份证系统“的设计意图

HandleManager就像身份证发放系统:

身份证系统类比:

身份证发放系统(HandleManager)
│
├── 职责:
│   ├── 发放身份证号(分配Handle)
│   ├── 记录身份证→人映射(Handle→Object映射)
│   ├── 验证身份证有效性(Handle有效性检查)
│   ├── 回收身份证(Handle回收)
│   └── 保证唯一性(Handle不重复)
│   │
│   ├── 身份证号特点:
│   │   ├── 唯一:每个号码唯一
│   │   ├── 不透明:号码本身不透露信息
│   │   ├── 可验证:可以验证是否有效
│   │   └── 可映射:号码对应具体人
│   │
│   ├── 身份证类型:
│   │   ├── Session身份证(CK_SESSION_HANDLE)
│   │   │   ├── 窗口编号
│   │   │   └── 用于所有后续操作
│   │   │
│   │   └── Object身份证(CK_OBJECT_HANDLE)
│   │   │   ├── 密钥/证书编号
│   │   │   ├── 用于密钥操作
│   │   │
│   │   └── 注意:两者是不同的类型!
│   │   │   ├── Session Handle:窗口编号
│   │   │   └── Object Handle:密钥编号
│   │   │   └── 不能混用
│   │
│   └── 身份证分配规则:
│   │   ├── 从1开始递增
│   │   ├── 不回收(不复用)
│   │   ├── 32位整数
│   │   └── 可以无限增长(直到溢出)
│   │
│   └── 身份证→人映射:
│   │   ├── map<Handle, Object>
│   │   ├── 查找:通过Handle找到Object
│   │   ├── 验证:检查Handle是否有效
│   │   └── 删除:删除Object时清除映射
│   │
└── 关键设计:
    ├── Handle是32位整数
    ├── Handle不透明(不透露内部信息)
    ├── Handle→Object映射表
    └── Handle不复用(简化设计)

HandleManager的地位

HandleManager负责分配和管理PKCS#11中的各种Handle:

Handle概念:

PKCS#11 Handle类型:
┌─────────────────────────────────────┐
│ CK_SESSION_HANDLE                   │
│ ├─ Session句柄                     │
│ ├─ OpenSession返回                 │
│ └─ 用于后续所有操作                │
│                                     │
│ CK_OBJECT_HANDLE                    │
│ ├─ 对象句柄                         │
│ ├─ CreateObject返回                 │
│ ├─ FindObjects返回                  │
│ ├─ GenerateKey返回                  │
│ └─ 用于密钥操作                    │
│                                     │
│ Handle特性:                         │
│ ├─ 32位整数                        │
│ ├─ 不透明(应用程序不理解)          │
│ ├─ 映射到内部对象                   │
│ └─ 会话关闭后失效                   │
└─────────────────────────────────────┘

HandleManager职责:
┌─────────────────────────────────────┐
│ ├─ 分配新Handle                     │
│ ├─ Handle→Object映射               │
│ ├─ Handle有效性验证                 │
│ ├─ Handle回收                       │
│ └─ Handle唯一性保证                 │
└─────────────────────────────────────┘

HandleManager类设计(教学简化说明)

注意:本章为教学目的简化了Handle管理机制。实际SoftHSM2源码使用统一的handles map管理所有类型句柄,而非分开的sessionHandles和objectHandles。SoftHSM2使用递增整数分配句柄,由Session和Token分别管理各自的对象句柄。

/* HandleManager类结构(简化模型) */

class HandleManager {
public:
    // Handle映射表(教学简化:分开存储便于理解)
    // 实际源码:统一的handles map
    std::map<CK_SESSION_HANDLE, Session*> sessionHandles;
    std::map<CK_OBJECT_HANDLE, Object*> objectHandles;
    
    // 下一个Handle值
    CK_SESSION_HANDLE nextSessionHandle;
    CK_OBJECT_HANDLE nextObjectHandle;
    
    // Handle分配
    CK_SESSION_HANDLE allocateSessionHandle(Session* session);
    CK_OBJECT_HANDLE allocateObjectHandle(Object* object);
    
    // Handle查询
    Session* getSession(CK_SESSION_HANDLE hSession);
    Object* getObject(CK_OBJECT_HANDLE hObject);
    
    // Handle验证
    bool isValidSessionHandle(CK_SESSION_HANDLE hSession);
    bool isValidObjectHandle(CK_OBJECT_HANDLE hObject);
    
    // Handle释放
    void releaseSessionHandle(CK_SESSION_HANDLE hSession);
    void releaseObjectHandle(CK_OBJECT_HANDLE hObject);
    
    // Session关闭时清理
    void cleanupSessionObjects(CK_SESSION_HANDLE hSession);
};

/* Handle分配实现 */

CK_SESSION_HANDLE HandleManager::allocateSessionHandle(Session* session)
{
    // 分配新Handle
    CK_SESSION_HANDLE handle = nextSessionHandle;
    nextSessionHandle++;
    
    // 避免Handle为0(无效值)
    if (handle == 0) {
        handle = nextSessionHandle;
        nextSessionHandle++;
    }
    
    // 存储映射
    sessionHandles[handle] = session;
    
    return handle;
}

CK_OBJECT_HANDLE HandleManager::allocateObjectHandle(Object* object)
{
    // 分配新Handle
    CK_OBJECT_HANDLE handle = nextObjectHandle;
    nextObjectHandle++;
    
    // 避免Handle为0(无效值)
    if (handle == 0) {
        handle = nextObjectHandle;
        nextObjectHandle++;
    }
    
    // 存储映射
    objectHandles[handle] = object;
    
    return handle;
}

/* Handle查询实现 */

Session* HandleManager::getSession(CK_SESSION_HANDLE hSession)
{
    // 查找映射表
    auto it = sessionHandles.find(hSession);
    if (it == sessionHandles.end()) {
        return NULL;
    }
    
    return it->second;
}

Object* HandleManager::getObject(CK_OBJECT_HANDLE hObject)
{
    // 查找映射表
    auto it = objectHandles.find(hObject);
    if (it == objectHandles.end()) {
        return NULL;
    }
    
    return it->second;
}

/* Handle验证实现 */

bool HandleManager::isValidSessionHandle(CK_SESSION_HANDLE hSession)
{
    // 检查Handle是否存在
    return sessionHandles.find(hSession) != sessionHandles.end();
}

bool HandleManager::isValidObjectHandle(CK_OBJECT_HANDLE hObject)
{
    // 检查Handle是否存在
    return objectHandles.find(hObject) != objectHandles.end();
}

/* Handle释放实现 */

void HandleManager::releaseSessionHandle(CK_SESSION_HANDLE hSession)
{
    // 从映射表删除
    sessionHandles.erase(hSession);
}

void HandleManager::releaseObjectHandle(CK_OBJECT_HANDLE hObject)
{
    // 从映射表删除
    objectHandles.erase(hObject);
}

Handle的生命周期

Handle生命周期:

Session Handle生命周期:
┌─────────────────────────────────────┐
│                                     │
│ C_OpenSession                       │
│     │                               │
│     │ Session创建                   │
│     │                               │
│     ▼                               │
│ HandleManager::allocateSessionHandle │
│     │                               │
│     │ 分配Handle                    │
│     │ hSession = 1                  │
│     │                               │
│     ├─────────────────────────────→ │
│     │                               │
│     │ 使用Handle                    │
│     │ C_Login(hSession, ...)        │
│     │ C_SignInit(hSession, ...)     │
│     │ C_Sign(hSession, ...)         │
│     │                               │
│     ├─────────────────────────────→ │
│     │                               │
│ C_CloseSession                      │
│     │                               │
│     │ Session删除                   │
│     │                               │
│     ▼                               │
│ HandleManager::releaseSessionHandle │
│     │                               │
│     │ Handle失效                    │
│     │                               │
│     └─→ Handle=1不再有效             │
│                                     │
│ 后续使用Handle=1:                   │
│ C_Login(1, ...) → CKR_SESSION_HANDLE_INVALID │
│                                     │
└─────────────────────────────────────┘

Object Handle生命周期:
┌─────────────────────────────────────┐
│                                     │
│ C_GenerateKey                       │
│     │                               │
│     │ Object创建                    │
│     │                               │
│     ▼                               │
│ HandleManager::allocateObjectHandle │
│     │                               │
│     │ 分配Handle                    │
│     │ hKey = 100                    │
│     │                               │
│     ├─────────────────────────────→ │
│     │                               │
│     │ 使用Handle                    │
│     │ C_SignInit(hSession, hKey)    │
│     │ C_EncryptInit(hSession, hKey) │
│     │                               │
│     ├─────────────────────────────→ │
│                                     │
│ Token对象:持久                      │
│ Session对象:随Session关闭失效       │
│                                     │
│ C_DestroyObject                     │
│     │                               │
│     │ Object删除                    │
│     │                               │
│     ▼                               │
│ HandleManager::releaseObjectHandle  │
│     │                               │
│     │ Handle失效                    │
│                                     │
└─────────────────────────────────────┘

Session关闭时的Handle清理

/* Session关闭时清理Object */

void HandleManager::cleanupSessionObjects(CK_SESSION_HANDLE hSession)
{
    // 获取Session
    Session* session = getSession(hSession);
    if (session == NULL) {
        return;
    }
    
    // 获取Session的Object列表
    std::vector<Object*> sessionObjects = session->getSessionObjects();
    
    // 释放所有Session Object Handle
    for (auto obj : sessionObjects) {
        // 找到Object的Handle
        for (auto it = objectHandles.begin(); it != objectHandles.end(); ++it) {
            if (it->second == obj) {
                // 释放Handle
                objectHandles.erase(it);
                break;
            }
        }
        
        // 删除Object
        delete obj;
    }
}

/* Session关闭完整流程 */

CK_RV SoftHSM::C_CloseSession(CK_SESSION_HANDLE hSession)
{
    // 1. 获取Session
    Session* session = sessionManager->getSession(hSession);
    if (session == NULL) {
        return CKR_SESSION_HANDLE_INVALID;
    }
    
    // 2. 清理Session Objects
    handleManager->cleanupSessionObjects(hSession);
    
    // 3. 清除Session操作状态
    session->clearAllOperations();
    
    // 4. 删除Session
    sessionManager->deleteSession(hSession);
    
    // 5. 释放Session Handle
    handleManager->releaseSessionHandle(hSession);
    
    return CKR_OK;
}

Handle映射冲突处理

/* Handle冲突检查 */

CK_SESSION_HANDLE HandleManager::allocateSessionHandle(Session* session)
{
    // 循环直到找到未使用的Handle
    while (true) {
        CK_SESSION_HANDLE handle = nextSessionHandle;
        nextSessionHandle++;
        
        // Handle为0无效
        if (handle == 0) {
            continue;
        }
        
        // 检查Handle是否已存在
        if (sessionHandles.find(handle) == sessionHandles.end()) {
            // Handle可用,存储映射
            sessionHandles[handle] = session;
            return handle;
        }
        
        // Handle冲突,继续尝试下一个
        // 这种情况很少发生,但理论上可能
    }
}

HandleManager在车载HSM中的应用

车载HSM Handle管理差异:

软件HSM(SoftHSM2):
┌─────────────────────────────────────┐
│ Handle分配方式:                     │
│                                     │
│ ├─ 简单整数递增                     │
│ ├─ std::map存储映射                 │
│ ├─ Handle可以很大                   │
│ └─ 无硬件限制                       │
│                                     │
│ Handle验证:                         │
│ ├─ 查map表                          │
│ ├─ 无硬件交互                       │
│ └─ 快速返回                         │
└─────────────────────────────────────┘

硬件HSM(车规级):
┌─────────────────────────────────────┐
│ Handle分配方式:                     │
│                                     │
│ ├─ HSM内部分配                      │
│ ├─ 可能映射到Key ID                 │
│ ├─ Handle范围有限                   │
│ └─ 需要APDU交互                    │
│                                     │
│ Handle验证:                         │
│ ├─ 发送APDU检查                     │
│ ├─ HSM返回有效性                   │
│ └─ 有通信开销                       │
│                                     │
│ Handle特殊性:                       │
│ ├─ 可能与Key ID绑定                 │
│ ├─ HSM内部管理                      │
│ ├─ Host只持有Handle                │
│ └─ 不能推测Handle含义               │
└─────────────────────────────────────┘

车规级HSM实例:
┌─────────────────────────────────────┐
│ Key ID vs Handle                    │
│                                     │
│ SDK层面:                            │
│ ├─ api_create_key() → key_id        │
│ ├─ key_id = 0x01, 0x02, ...         │
│ └─ 固定范围                         │
│                                     │
│ PKCS#11封装:                        │
│ ├─ key_id映射到CK_OBJECT_HANDLE     │
│ ├─ Handle = 0x01, 0x02              │
│ └─ 简单映射                         │
│                                     │
│ 限制:                               │
│ ├─ Key ID有限(取决于HSM)          │
│ ├─ Handle不能超出Key ID范围          │
│ └─ 不是无限递增                     │
└─────────────────────────────────────┘

小结:Handle管理要点

Handle管理要点回顾:

1. Handle概念
   32位整数
   不透明标识符
   映射到内部对象

2. HandleManager职责
   分配新Handle
   Handle→Object映射
   Handle验证
   Handle回收

3. Handle分配算法
   简单递增
   避免为0
   检查冲突
   唯一性保证

4. Handle生命周期
   创建时分配
   使用时验证
   关闭/销毁时释放
   Session关闭影响Session Objects

5. 车载HSM差异
   软件HSM:简单映射
   硬件HSM:Key ID绑定
   Handle范围可能有限

6. 关键验证
   所有PKCS#11函数验证Handle
   CKR_SESSION_HANDLE_INVALID
   CKR_KEY_HANDLE_INVALID
   Handle失效后必须重新创建

HandleManager是对象管理的“身份证发放中心“,确保Handle的唯一性和有效性。

下一节,我们将深入存储模块——看Object如何被持久化。

【下集预告】

Object怎么存储?

文件存储和数据库存储有什么区别?

ObjectFile是什么结构?

下一节,Object存储架构。