一、实验目的:
- 熟悉数据密封的要求和方法;
- 熟悉数据分块封装方法;
- 熟悉外部数据与TPM内部PCR寄存器的关联方法;
- 掌握硬件相关的程序设计流程和实现步骤。
二、实验内容、步骤及结论
1. 实验内容
- 设计可信文件存储系统,实现文件密封。
可信计算中,针对TPM的功能可以对数据进行封装SEAL操作,该封装操作利用公钥对数据进行加密,同时封装操作需要进行授权,并且可以将PCR的值与数据一起封装,TPM与数据绑定。只有当计算机当前状态达到PCR值时,封装的数据才可以进行解封装操作。
2. 实验步骤
1.启动相关模块
(1)启动TPM
sudo su
modprobe tpmd_dev
tpmd -f -d //-d 进入debug 模式 -f 使应用在前台运行
(2) 启动tcsd
sudo su
tcsd -e -f
(3) 设置owner和SRK密码
tpm_takeownership -u
(4) 编写代码
封装的结构体及封装函数的示例片段如下:
typedef struct tdTPM_SEALED_DATA
{
TPM_PAYLOAD_TYPE payload;
TPM_SECRET authData;
TPM_NONCE tpmProof;
TPM_DIGEST storedDigest;
UINT32 dataSize;
BYTE *data;
} TPM_SEALED_DATA;
int MyFunc_SealData(TSS_HKEY hKey, TSS_HPCRS hPcrs, UINT32 in_size, BYTE *in,
UINT32 *out_size, BYTE *out)
{
TSS_HENCDATA hEncData;
UINT32 keySize, tmp_out_size;
BYTE *tmp_out;
/* Create the encrypted data object in the TSP */
Tspi_Context_CreateObject(hContext,
TSS_OBJECT_TYPE_ENCDATA,
TSS_ENCDATA_SEAL, &hEncData );
Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
TSS_TSPATTRIB_KEYINFO_SIZE, &keySize); /* Make sure the data is small enough to be bound by this key,taking into account the
OAEP padding size (38) and the size of the TPM_SEALED_DATA structure (65) */
if (in_size > keySize – 103) {
LogError( “Data to be encrypted is too big! ”);
return -1;
}
Tspi_Data_Seal(hEncData, hKey, in_size, in, hPcrs);
/* Now hEncData contains an encrypted blob, let’s extract it */
Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB,
TSS_TSPATTRIB_ENCDATABLOB_BLOB,&tmp_out_size, &tmp_out);
if (tmp_out_size > *out_size) {
LogError( “Encrypted data blob is too big! ”);
return -1;
}
/* Copy the encrypted data blob to the user ’s buffer */
memcpy(out, tmp_out, tmp_out_size);
*out_size = tmp_out_size;
/* Free the blob returned by the TSP */
Tspi_Context_FreeMemory( hContext, tmp_out);
/* Close the encrypted data object, it will no longer be used */
Tspi_Context_CloseObject( hContext, hEncData);
return 0;
}
代码调用的接口顺序为
- Tspi_Context_Create (&hContext):创建上下文对象
- Tspi_Context_Connect (hContext,NULL):连接上下文
- Tspi_Context_GetTpmObject (hContext,&hTPM):获得隐式创建的TPM对象的句柄
- Tspi_GetPolicyObject (hTPM,TSS_POLICY_USAGE,&hownerpolicy):获得TSP隐式创建的策略对象
- Tspi_Policy_SetSecret (hownerpolicy,TSS_SECRET_MODE_POPUP,0,NULL):设置秘密
- Tspi_Context_LoadKeyByUUID (hContext,TSS_PS_TYPE_SYSTEM,SRK_UUID,&hSRK):根据UUID加载SRK密钥
- Tspi_GetPolicyObject (hSRK,TSS_POLICY_USAGE,&hSRKPolicy):获得SRK的策略对象
- Tspi_Policy_SetSecret (hSRKPolicy,TSS_SECRET_MODE_POPUP,0,NULL):设置SRK的策略授权
- Tspi_Context_CreateObject (hContext,TSS_OBJECT_TYPE_RSAKEY,initFlags,&hkey):设置好密钥标记initFlags后创建绑定密钥,hkey中存储加密的数据块
- Tspi_Context_CreateObject(hContext,TSS_OBJECT_TYPE_PCRS,0,&hPCRs);创建PCR对象
- Tspi_TPM_PcrRead(hTPM, 8,&ulPcrLen, &rbgPcrValue);读取PCR8中的数据
- Tspi_PcrComposite_SetPcrValue(hPCRs,8,20,rbgPcrValue);将读取到的PCR8中的值写入PCR对象中
- Tspi_TPM_PcrRead(hTPM, 9,&ulPcrLen, &rbgPcrValue); 读取PCR9中的数据
- Tspi_PcrComposite_SetPcrValue(hPCRs,9,20,rbgPcrValue); 将读取到的PCR9中的值写入PCR对象中
- Tspi_Context_CreateObject (hContext,TSS_OBJECT_TYPE_ENCDATA,TSS_ENCDATA_SEAL,&hEnc Data ):创建TSP中被加密数据对象
- Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,TSS_TSPATTRIB_KEYINFO_SIZE,&key Size):获取密钥对象的属性。执行这步后,要比较待加密数据长度与keySize-103的大小,以防加密数据过大
- Tspi_Data_Seal(hEncData, hKey, in_size, in, hPCRs):数据密封
- Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB,TSS_TSPATTRIB_ENCDATABLOB_ BLOB,&tmp_out_size, &tmp_out):执行这步后要比较tmp_out_size 和*out_size大小,以防被加密的blob过大
- memcpy(out, tmp_out, tmp_out_size):复制被加密的blob到用户的buffer中
- Tspi_Context_FreeMemory( hContext, tmp_out):释放由TSP返回的blob
- Tspi_Context_CloseObject( hContext, hEncData):关闭被加密的数据对象
- Tspi_Context_Close(hContext):关闭上下文
(5) 编译并运行代码
sudo su
gcc -o seal_data seal_data.c -ltspi
./seal_data
Download:
3. 实验结论
likewise sb