TPM 程序设计基础 2-1 :具体函数调用步骤及解析示例
前言
本文简述调用 Tspi 相关函数的前提、要求、过程、结果。
代码示例
-
请下载示例代码:pcr_read.c
-
代码实现功能:
- 声明 TPM 相关句柄和变量
- 调用 Tspi_TPM_PcrRead() 等相关函数
- 输出 PCR 读取结果
-
主要结构如下:
// 导入头文件 #include ...... // 设置 define 宏 #define Debug(message, tResult) ... // 声明句柄,调用相关函数,输出结果 void pcr_read() {} // 调用 void pcr_read() 函数 int main() {}
void pcr_read() 函数读取 PCR 值
我们来分析如何实现最终目的:输出 PCR 读取结果。
选择 read 函数
-
由于要读取 PCR 寄存器内的值,锁定关键词为
pcr
和read
,所以可以找到函数:Tspi_TPM_PcrRead()
-
到原英文文档中找到该函数,或者参阅 TPM 程序设计基础 1-2-2 :旧的 PCR 命令 。
声明参数
-
得知函数使用的参数,简单列出:
TSS_HTPM hTPM, // [in]TPM 句柄 UINT32 ulPcrIndex, // [in]PCR寄存器的序号 UINT32* pulPcrValueLength, // [out]选定PCR寄存器的数据长度 BYTE** prgbPcrValue // [out]选定PCR寄存器的数据内容
-
所以声明这些参数。
-
并且在这个函数的定义开始,有个
TSS_RESULT
:TSS_RESULT Tspi_TPM_PcrRead ( ....... );
-
还需要声明
TSS_RESULT
类型的参数,作为Tspi_TPM_PcrRead()
返回的句柄。 -
到此时,得到
pcr_read()
程序内容:void pcr_read() { TSS_HTPM hTPM; TSS_RESULT result; UINT32 ulPcrIndex; UINT32 pulPcrValueLength; BYTE* prgbPcrValue; result = Tspi_TPM_PcrRead(hTPM, ulPcrIndex, &pulPcrValueLength, &prgbPcrValue); }
-
但是标有
[in]
标志的hTPM
和ulPcrIndex
都为NULL
,需要赋予它们内容。ulPcrIndex
范围是 0-23 ,原因:TSS V1.2 有 24个 PCR 寄存器。hTPM
是 TPM 句柄,需通过其他函数返回。
获得 TPM 句柄
要获得 TPM 句柄,需要使用 Tspi_Context_GetTpmObject()
函数。
-
到原英文文档中找到该函数,或者参阅 TPM 程序设计基础 1-2-1 :Tspi_Context 类定义 。
-
该函数参数:
TSS_HCONTEXT hContext, // [in]上下文对象的句柄 TSS_HTPM* phTPM // [out] TPM 句柄
-
声明上下文对象的句柄
hContext
。 -
到此时,得到
pcr_read()
程序内容:Server.java
void pcr_read() { TSS_HTPM hTPM; TSS_RESULT result; TSS_HCONTEXT hContext; UINT32 ulPcrIndex; UINT32 pulPcrValueLength; BYTE* prgbPcrValue; //获得 TPM 句柄 result = Tspi_Context_GetTpmObject(hContext, &hTPM); //设置读取的 PCR 的 index ulPcrIndex = 0; //读取 index 的 PCR result = Tspi_TPM_PcrRead(hTPM, ulPcrIndex, &pulPcrValueLength, &prgbPcrValue); }
-
但是又有一个标有
[in]
标志的hContext
为NULL
,需要赋予它内容。hContext
是上下文对象的句柄,需通过其他函数返回。
获得 上下文对象 句柄
要获得 TPM 句柄,需要使用 Tspi_Context_Create()
和 Tspi_Context_Connect()
函数。
Tspi_Context_Create()
返回 新上下文对象的句柄。
-
到原英文文档中找到该函数,或者参阅 TPM 程序设计基础 1-2-1 :Tspi_Context 类定义 。
-
该函数参数:
TSS_HCONTEXT hContext, // [out]上下文对象的句柄
-
获得上下文对象的句柄
hContext
。
Tspi_Context_Connect()
建立到本地或远程TSS系统的连接。
-
到原英文文档中找到该函数,或者参阅 TPM 程序设计基础 1-2-1 :Tspi_Context 类定义 。
-
该函数参数:
TSS_HCONTEXT hContext, // [in]上下文对象的句柄 TSS_UNICODE* wszDestination // [in]指向空终止的TSS_UNICODE字符串的指针
wszDestination
:该字符串指定要连接的远程系统。如果为空,则上下文对象绑定到本地系统。 这里设定为NULL
。
-
到此时,得到
pcr_read()
程序内容:Server.java
void pcr_read() { TSS_HTPM hTPM; TSS_RESULT result; TSS_HCONTEXT hContext; UINT32 ulPcrIndex; UINT32 pulPcrValueLength; BYTE* prgbPcrValue; //获取 上下文对象 句柄 result = Tspi_Context_Create(&hContext); //建立与本地 TPM 的连接 result = Tspi_Context_Connect(hContext, NULL); //获得 TPM 句柄 result = Tspi_Context_GetTpmObject(hContext, &hTPM); //设置读取的 PCR 的 index ulPcrIndex = 0; //读取 index 的 PCR result = Tspi_TPM_PcrRead(hTPM, ulPcrIndex, &pulPcrValueLength, &prgbPcrValue); }
释放 hContext 占用的内存
Tspi_Context_FreeMemory(hContext, NULL);
Tspi_Context_Close(hContext);
- 现在,整个
pcr_read()
程序已经实现了从 TPM 的第 0 个 PCR 寄存器中读取了其中的值,存储到prgbPcrValue
中。 - 当每个函数的每个句柄都能获得,说明程序的调用链是完整的。
void pcr_read() 函数输出 PCR 值
-
由于
prgbPcrValue
的数据类型为BYTE**
,是一个指针,指向长度为pulPcrValueLength
的存储了第 0 个 PCR 寄存器值的内存块。 -
这里
pulPcrValueLength
一般为 20 ,单独BYTE
类型长度为 8 个 0/1 。 -
要输出其中的值,必须要按照
0X
(十六进制)显示输出。 -
然后输出从 0 到 23 个的 PCR 寄存器中的值。
void pcr_read() { TSS_HTPM hTPM; TSS_RESULT result; TSS_HCONTEXT hContext; UINT32 ulPcrIndex; UINT32 pulPcrValueLength; BYTE* prgbPcrValue; result = Tspi_Context_Create(&hContext); result = Tspi_Context_Connect(hContext, NULL); result = Tspi_Context_GetTpmObject(hContext, &hTPM); for (int j = 0; j < 24; j++) { result = Tspi_TPM_PcrRead(hTPM, j, &pulPcrValueLength, &prgbPcrValue); printf("PCR %02d ", j); for (int i = 0; i < 20; i++) { printf("%02x", *(prgbPcrValue + i)); } printf("\n"); } Tspi_Context_FreeMemory(hContext, NULL); Tspi_Context_Close(hContext); }
编译、运行结果
-
编译 pcr_read.c。
gcc pcr_read.c -o pcr_read.out -ltspi
-
运行 pcr_read.out。
./pcr_read.out
- 我这里的 PCR 01 和 08 是已经扩展过的值。
- 一般来说,没有扩展过的 PCR 值:
- 0-15 个为全
0
; - 16-23 个为全
f
。
- 0-15 个为全