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

3.9 硬件特征对象:密码设备独有的“特异功能“

硬件特征对象概述

PKCS#11规范第4.3节定义了一种特殊对象类型——硬件特征对象(CKO_HW_FEATURE),代表密码设备(Token)的硬件特性。

硬件特征对象分类:

CKO_HW_FEATURE(硬件特征对象类)
├── CKH_CLOCK             时钟对象(实时时钟)
├── CKH_MONOTONIC_COUNTER  单调计数器对象
└── CKH_USER_INTERFACE     用户界面对象

与其他对象的区别

特性普通对象硬件特征对象
创建方式C_CreateObject由Token自动创建
存储位置Token存储区直接代表硬件功能
数量可创建多个每类通常只有1个
查找行为默认可见需显式指定CKA_CLASS

查找约束:使用C_FindObjectsInit查找时,硬件特征对象不会被返回,除非模板中显式指定:

CK_OBJECT_CLASS hwClass = CKO_HW_FEATURE;
CK_ATTRIBUTE template[] = {
    {CKA_CLASS, &hwClass, sizeof(hwClass)}
};
rv = C_FindObjectsInit(hSession, template, 1);
// 只有指定CKO_HW_FEATURE才会返回硬件特征对象

设计意图:保护旧版本应用程序不会“意外“发现不理解的新对象类型。


时钟对象(Clock Object)

时钟对象(CKH_CLOCK)代表Token上的实时时钟。

时钟对象架构:

┌─────────────────────────────────┐
│ Token(HSM硬件)                │
│                                 │
│  ┌───────────────────────────┐ │
│  │ 实时时钟(RTC)            │ │
│  │ - 硬件时钟芯片            │ │
│  │ - 电池供电(断电保持)    │ │
│  │ - 高精度时间源            │ │
│  └───────────────────────────┘ │
│              │                  │
│              ▼                  │
│  ┌───────────────────────────┐ │
│  │ Clock对象                  │ │
│  │ CKA_HW_FEATURE_TYPE       │ │
│  │   = CKH_CLOCK             │ │
│  │ CKA_VALUE = 时间字符串     │ │
│  └───────────────────────────┘ │
│              │                  │
│              ▼                  │
│  CK_TOKEN_INFO.utcTime         │
│  (同一时钟源)                 │
└─────────────────────────────────┘

属性

属性数据类型含义
CKA_HW_FEATURE_TYPECK_HW_FEATURE_TYPECKH_CLOCK
CKA_VALUECK_CHAR[16]当前时间字符串

时间格式YYYYMMDDhhmmssxx

格式分解:

YYYY  - 年份(4字符)
MM    - 月份(2字符,01-12)
DD    - 日期(2字符,01-31)
hh    - 小时(2字符,00-23)
mm    - 分钟(2字符,00-59)
ss    - 秒(2字符,00-59)
xx    - 保留字段(2字符,表示时区偏移,如'00'=UTC、'+08'=东八区)

示例:2023121514305300
→ 2023年12月15日 14:30:53

修改时间

CK_CHAR newTime[16] = "2024010100000000";
CK_ATTRIBUTE setTime = {CKA_VALUE, newTime, 16};

/* 设置时间需要登录 */
rv = C_SetAttributeValue(hSession, hClock, &setTime, 1);

if (rv == CKR_USER_NOT_LOGGED_IN) {
    // 可能需要SO权限
    rv = C_Login(hSession, CKU_SO, soPin, soPinLen);
    rv = C_SetAttributeValue(hSession, hClock, &setTime, 1);
}

安全约束

  • 设置时间需要登录Session
  • 某些Token要求SO(Security Officer)权限
  • 返回CKR_USER_NOT_LOGGED_IN表示权限不足

单调计数器对象(Monotonic Counter)

单调计数器(CKH_MONOTONIC_COUNTER)代表硬件计数器,每次读取值都会增加。

单调计数器特性:

读取前:counter_value = 12345
读取后:counter_value = 12346(或更大)

关键特性:
- 保证每次读取都增加
- 增加量不一定为1(取决于硬件)
- 不能设置、不能回退、不能重置(除非C_InitToken)

属性

属性数据类型含义
CKA_HW_FEATURE_TYPECK_HW_FEATURE_TYPECKH_MONOTONIC_COUNTER
CKA_RESET_ON_INITCK_BBOOLC_InitToken时是否重置
CKA_HAS_RESETCK_BBOOL是否曾被重置
CKA_VALUEByte array当前计数值(大端序)

重要约束:CKA_VALUE只能读取,不能设置!

/* 读取计数器 */

CK_BYTE counterValue[8];
CK_ATTRIBUTE getValue = {CKA_VALUE, counterValue, sizeof(counterValue)};
rv = C_GetAttributeValue(hSession, hCounter, &getValue, 1);

/* 尝试设置会失败 */

CK_BYTE newValue[8] = {0};
CK_ATTRIBUTE setValue = {CKA_VALUE, newValue, sizeof(newValue)};
rv = C_SetAttributeValue(hSession, hCounter, &setValue, 1);
// 返回CKR_ATTRIBUTE_READ_ONLY

单调计数器的安全意义

单调计数器是防御重放攻击的关键工具。

重放攻击场景:

攻击者截获消息:
Message_1 = {command: "解锁车门", counter: 100, signature: ...}

攻击者重放:
Message_2 = {command: "解锁车门", counter: 100, signature: ...}
                    ↑ 相同计数器值 → 重放!

防御机制:
每次收到消息,检查counter是否大于上次记录的值:
- counter > last_counter → 接受,更新last_counter
- counter <= last_counter → 拒绝,疑似重放攻击

车载应用场景

车载安全消息序列:

┌───────────────────────────────────────┐
│ Host应用程序                           │
│                                       │
│ 1. 读取HSM单调计数器                   │
│    counter = 1001                     │
│                                       │
│ 2. 构造安全消息                        │
│    message = {                        │
│      command: "解锁车门",              │
│      counter: 1001,                   │
│      timestamp: 当前时间               │
│    }                                  │
│                                       │
│ 3. HSM签名                            │
│    signature = Sign(privateKey,       │
│                     message)          │
│                                       │
│ 4. 发送消息                           │
│    → {message, signature}             │
└───────────────────────────────────────┘

接收端验证:
- 检查counter是否递增
- 检查签名有效性
- 防止攻击者重放旧消息

CKA_RESET_ON_INIT与CKA_HAS_RESET

这两个属性控制计数器的“生命周期“:

计数器重置场景:

场景1:正常使用(不重置)
┌─────────────────┐
│ Token初始化     │
│ C_InitToken     │ → 计数器保持原值
└─────────────────┘
CKA_RESET_ON_INIT = FALSE
CKA_HAS_RESET = FALSE(从未重置)

场景2:强制重置
┌─────────────────┐
│ Token重新初始化  │
│ C_InitToken     │ → 计数器重置为初始值
└─────────────────┘
CKA_RESET_ON_INIT = TRUE(支持重置)
CKA_HAS_RESET = TRUE(已被重置)

安全考虑

  • 如果CKA_RESET_ON_INIT = FALSE,计数器值跨Token初始化保持,提供更强的防重放能力
  • 如果CKA_RESET_ON_INIT = TRUE,每次C_InitToken会重置,可能削弱安全性

用户界面对象(User Interface)

用户界面对象(CKH_USER_INTERFACE)代表Token的人机交互能力。

用户界面对象适用场景:

传统HSM:
- 无显示屏、无键盘
- 通过Host计算机操作

智能卡/USB Token:
- 可能带有PIN输入键盘
- 可能带有小型显示屏
- 用于安全PIN输入

ATM/POS终端:
- 大屏幕显示
- 键盘输入
- 用户交互界面

属性

属性数据类型含义
CKA_PIXEL_XCK_ULONGX轴像素分辨率(如1280)
CKA_PIXEL_YCK_ULONGY轴像素分辨率(如1024)
CKA_RESOLUTIONCK_ULONGDPI像素密度
CKA_CHAR_ROWSCK_ULONG字符显示行数(如24)
CKA_CHAR_COLUMNSCK_ULONG字符显示列数(如80)
CKA_COLORCK_BBOOL是否支持彩色显示
CKA_BITS_PER_PIXELCK_ULONG每像素位数
CKA_CHAR_SETSRFC2279 string支持的字符集
CKA_ENCODING_METHODSRFC2279 string支持的编码方法
CKA_MIME_TYPESRFC2279 string支持的MIME类型

车载HSM的硬件特征对象配置

车载HSM通常支持以下硬件特征对象:

车载HSM硬件特征:

时钟对象(CKH_CLOCK)
├── 用途:安全消息时间戳
├── 来源:HSM内部RTC
├── 特性:断电保持(电池供电)
└── 精度:通常±1秒/天

单调计数器(CKH_MONOTONIC_COUNTER)
├── 用途:防重放攻击
├── 特性:每次读取自增
├── 存储:Flash(持久化)
└── 重置:C_InitToken后可能重置

用户界面对象(CKH_USER_INTERFACE)
├── 车载HSM通常:无显示屏
├── Host MCU:承担显示职责
└── 因此:通常不支持此对象

典型车规级HSM的配置

车规级HSM硬件特征支持:

时钟对象:
- 通常支持
- 可通过APDU指令读取/设置
- 与安全消息签名关联

单调计数器:
- 通常支持
- 用于防重放序列号
- 集成在安全消息协议中

用户界面:
- 不支持(无显示屏)

小结:硬件特征对象的价值

硬件特征对象代表密码设备“超越密码“的特异功能:

核心价值回顾:

时钟对象
├── 安全时间戳来源
├── 证书有效期验证参考
├── 审计日志时间基准
└── 与CK_TOKEN_INFO.utcTime共享时钟源

单调计数器
├── 防重放攻击的关键工具
├── 保证序列号唯一递增
├── 硬件级别的不可回退
└── 安全消息协议必备

用户界面对象
├── 安全PIN输入通道
├── 独立于Host的交互能力
├── 防止Host端截获PIN
└── 智能卡/USB Token常用

设计哲学:
- 硬件特征对象"映射"真实硬件能力
- 不是虚拟对象,而是硬件接口
- 扩展PKCS#11的能力边界
- 从"密码计算"到"安全设备"

这些硬件特征对象,让HSM不仅仅是“密码计算器“,而是完整的“安全设备“。 下一节,我们将学习初始化函数——看PKCS#11的启动流程。

【下集预告】

C_Initialize做什么?C_Finalize做什么?

C_GetSlotList怎么用?C_InitToken怎么初始化?

初始化顺序是什么?

下一节,初始化与Slot管理函数。