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存储架构。