1. 程式人生 > 其它 >tpm_emulator 搭建 TPM 模擬環境

tpm_emulator 搭建 TPM 模擬環境

目錄
1. 平臺環境
1.1. 系統平臺
1.2. TPM 模擬環境結構
2. cmake
2.1. cmake 簡介
2.2. 安裝 cmake
3. m4
3.1. m4 簡介
3.2. 安裝 m4
4. GNU MP Library
4.1. GMP 簡介
4.2. 安裝 GMP
5. TPM_Emulator
5.1. 編譯和安裝 TPM_Emulator
5.2. 初始化 TPM_Emulator
5.3. 啟動 TPM_Emulator
6. TSS 協議棧
6.1. 編譯和安裝 Trousers
6.2. 啟動 TCSD
7. tpm-tools
7.1. tpm-tools 簡介
7.2. 安裝 tpm-tools
8. 測試 TPM 環境是否搭建成功
9. 執行測試程式
9.1. 在 tpm-emulator-0.7.5/tddl/ 目錄下有測試程式
PS:解決後再更新???
9.2. 對TSS協議棧進行測試
9.2.1. 測試程式
9.2.2. 該程式實現的操作
9.2.3. 編譯和執行
PS:解決後再更新???
1. 平臺環境
1.1. 系統平臺
宿主機系統:Windows 10 Pro
虛擬機器工具:VMware® Workstation 15 Pro
虛擬機器系統:CentOS Linux release 7.6.1810 (Core) 64位
本文在 centos 虛擬機器上搭建 TPM 模擬環境。

1.2. TPM 模擬環境結構
下面是TPM模擬環境軟體包依賴關係圖,搭建環境應該是由下至上按部就班的安裝。

 

 


2. cmake
2.1. cmake 簡介
CMake 是一個跨平臺的自動化建構系統,它使用一個名為 CMakeLists.txt 的檔案來描述構建過程,可以產生標準的構建檔案,如 Unix 的 Makefile 或Windows Visual C++ 的 projects/workspaces 。檔案 CMakeLists.txt 需要手工編寫,也可以通過編寫指令碼進行半自動的生成。CMake 提供了比 autoconfig 更簡潔的語法。在 linux 平臺下使用 CMake 生成 Makefile 並編譯的流程如下:
(1)編寫 CmakeLists.txt。
(2)執行命令“cmake PATH”或者“ccmake PATH”生成 Makefile ( PATH 是 CMakeLists.txt 所在的目錄 )。
(3)使用 make 命令進行編譯。

2.2. 安裝 cmake

 

 3. m4

3.1. m4 簡介
m4 是一種巨集處理器,它掃描使用者輸入的文字並將其輸出,期間如果遇到巨集就將其展開後輸出。巨集有兩種,一種是內建的,另一種是使用者自定義的,它們能接受任意數量的引數。除了做展開巨集的工作之外,m4 內建的巨集能夠載入檔案,執行 Shell 命令,做整數運算,操縱文字,形成遞迴等等。m4 可用作編譯器的前端,或者單純作為巨集處理器來用。

3.2. 安裝 m4

 

 4. GNU MP Library

4.1. GMP 簡介
gmp是一個可以進行任意精度算術的自由庫,可以操作有符號整數、有理數和浮點數。除了執行gmp的機器中可用記憶體所暗示的精度外,沒有實際限制。gmp有一套豐富的功能,這些功能有一個常規的介面(本文不研究這個介面)。
gmp的主要目標應用是密碼學應用與研究、網際網路安全應用、代數系統、計算代數研究等。
gmp基於m4,所以在安裝gmp之前要先安裝m4。

4.2. 安裝 GMP
下載地址:http://gmplib.org

我下載的版本:gmp-6.1.2.tar.bz2

執行下列命令進行編譯和安裝:

 

 Tips:

還有 gmp-6.1.2.tar.lz 版本的壓縮包,它是使用 lzip 工具生成的,需要使用 lunzip 工具進行解壓。
lzip下載地址:http://www.nongnu.org/lzip/lzip.html
lunzip下載地址:http://www.nongnu.org/lzip/lunzip.html

5. TPM_Emulator
下載地址:https://github.com/PeterHuewe/tpm-emulator/releases

我下載的版本:tpm-emulator-0.7.5.tar.gz

該程式主要包含三個部分:
(1)tpmd:實現 TPM 模擬器的使用者空間應用程式,可以通過 Unix 域套接字(Unix)或命名管道(Windows)進行訪問。
(2)tpmd_dev:一個核心模組,它提供裝置 /dev/tpm 以實現向後相容,並將收到的命令轉發給 tpmd(僅限Unix和Mac OS X)。

向後相容(Backward Compatibility),又稱作向下相容(Downward Compatibility)。在計算機中指在一個程式或者類庫更新到較新的版本後,用舊的版本程式建立的文件或系統仍能被正常操作或使用,或在舊版本的類庫的基礎上開發的程式仍能正常編譯執行的情況。

(3)tddl:TPM 模擬器的 TSS 符合裝置驅動程式庫。

 

 


5.1. 編譯和安裝 TPM_Emulator
TPM 模擬器包的編譯和安裝基於 CMake 構建環境(2.6或更高版本),並要求在您的系統上正確安裝 GNU MP 庫(版本4.0或更高版本)。因為前面已經安裝過了,所以這裡直接執行下列命令進行編譯和安裝:

 

 

我在執行 make 時遇到的錯誤:

 

 


原因:

提示 /lib/modules/3.10.0-957.10.1.el7.x86_64/build 軟連結沒有指向正確的 kernel source,後來知道因為那個檔案根本就不存在,我們需要下載它。

解決方法:
(1)看一下 build 軟連結指向哪個檔案:

 

 在 centos 7.x 下 build -> /usr/src/kernels/3.10.0-957.10.1.el7.x86_64 不停地閃爍,說明 /usr/src/kernels/3.10.0-957.10.1.el7.x86_64 不存在。

(2)進入 /usr/src/kernels/ 目錄,看一下有沒有相應的核心開發包 3.10.0-957.10.1.el7.x86_64:

 

 沒有則下載。

(3)下載 3.10.0-957.10.1.el7.x86_64 核心開發包:

 

 再次執行 make 就沒問題了。

5.2. 初始化 TPM_Emulator
TPM的啟動模式(參見TPM規範第1部分)由啟動模式引數定義,可以設定為clear,save(預設)或deactivated,對應的中文意思分別是清除,儲存和停用。 下面簡單介紹tpmd的用法以及引數的含義:

 

 如果模擬器以“save”模式啟動並且無法載入先前儲存的TPM狀態,則它將進入“fail-stop”模式並且必須重新載入。 因此,第一次啟動TPM模擬器時,引數必須設定為“clear”。 想要恢復處於“fail-stop”模式的TPM模擬器,首先將其停用,然後以“clear”模式重新載入,我們執行下列命令進行初始化:

 

 

5.3. 啟動 TPM_Emulator
要想在 Unix 或 Mac OS X 上使用 TPM 模擬器,必須先啟動 TPM 模擬器的守護程式(tpmd)並載入 TPM 裝置轉發模組(tpmd_dev)。 我們執行下列命令進行啟動:

 

 註釋:

(1)若在執行第一條命令時遇到:Module tpmd_dev not found,則執行命令:depmod -a

(2)modprobe命令:
modprobe命令用於智慧地向核心中載入模組或者從核心中移除模組。
modprobe可載入指定的個別模組,或是載入一組相依的模組。modprobe會根據depmod所產生的相依關係,決定要載入哪些模組。若在載入過程中發生錯誤,在modprobe會解除安裝整組的模組。

(3)depmod命令:
depmod命令可產生模組依賴的對映檔案,在構建嵌入式系統時,需要由這個命令來生成相應的檔案,由modprobe使用。

啟動時遇到的錯誤:

 

 


解決方法:

 

 

再次啟動 tpmd 就沒有問題了。

6. TSS 協議棧
下載地址:https://sourceforge.net/projects/trousers/files/

我下載的版本:trousers-0.3.14.tar.gz

該程式是由 IBM 建立和釋出的開源 TCG 軟體棧。

6.1. 編譯和安裝 Trousers
Tips:
如果直接解壓 trousers 的壓縮包,它的各種檔案會分散在父目錄裡面,所以要在解壓時為其指定一個解壓目錄。當然,如果不小心直接解壓了,也可以使用下列命令撤銷解壓操作:

 

 


我們先為 trousers 建立一個目錄,再將其進行解壓:

 

 


看一下 README 檔案,並按要求安裝如下的依賴包:

 

 


安裝完上述的依賴包後再執行下面的命令進行編譯和安裝:

 

 


Tips:
網上有說需要修改 Makefile.am 和 Makefile.in 檔案,但那些都是 trousers-0.3.8 版本的教程,那個版本會遇到 Werror、ld 連結庫等報錯的問題。本文使用 trousers-0.3.14 版本,沒有修改 Makefile.* 檔案,直接編譯安裝成功無報錯。

6.2. 啟動 TCSD
Tips:
在執行下列命令之前需要先啟動 TPM_Emulator,否則會提示找不到裝置。

 

 

啟動時遇到的錯誤:

 

 


解決方法:
帶上 clear 引數重啟 tpm-emulator:

 

 再次啟動 tcsd 就沒有問題了。

7. tpm-tools
7.1. tpm-tools 簡介
tpm-tools 是一組管理和利用可信計算組織的 TPM 硬體的工具。 TPM 硬體可以安全地建立,儲存和使用 RSA金鑰(不會暴露在記憶體中),使用加密雜湊等來驗證平臺的軟體狀態。該程式包含的工具允許平臺管理員管理和診斷平臺的 TPM 硬體。 此外,該程式還包含命令,以利用 openCryptoki 專案中實現的 TPM PKCS#11 介面中提供的某些功能。

7.2. 安裝 tpm-tools

 

 


8. 測試 TPM 環境是否搭建成功
(1)先啟動 tpmd
(2)再啟動 tcsd
(3)最後使用 tpm-tools 工具的命令加以驗證:

 

 


要執行 tpm-tools 工具的命令,必須先啟動 tpmd 和 tcsd,缺一不可。

9. 執行測試程式
9.1. 在 tpm-emulator-0.7.5/tddl/ 目錄下有測試程式
在編譯時連結 libtddl.a 靜態庫,編譯時沒有問題,執行時出現如下錯誤:

 

 PS:解決後再更新???

9.2. 對TSS協議棧進行測試
9.2.1. 測試程式
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tss/platform.h>
#include <tss/tss_error.h>
#include <tss/tss_defines.h>
#include <tss/tss_structs.h>
#include <tss/tss_typedef.h>
#include <tss/tss_error_basics.h>
#include <tss/tspi.h>
#include <trousers/tss.h>
#include <tss/tpm.h>

const char *get_error(TSS_RESULT res)
{
switch(ERROR_CODE(res))
{
case 0x0001L:
return "Authentication failed";
case TSS_SUCCESS:
return "success";
case TSS_E_INVALID_HANDLE:
return "hContext or phObject is an invalid handle";
case TSS_E_BAD_PARAMETER:
return "persistentstoragetype is not valid/One or more parameters is incorrect";
case TSS_E_INTERNAL_ERROR:
return "an error occurred internal to the TSS";
case TSS_E_PS_KEY_NOTFOUND:
return "NOT FOUND SRK";
case TSS_E_INVALID_ATTRIB_FLAG:
return "attribflag is incorrect";
case TSS_E_INVALID_ATTRIB_SUBFLAG:
return "subflag is incorrect";
case TSS_E_INVALID_ATTRIB_DATA:
return "ulAttrib is incorrect";
case TSS_E_KEY_ALREADY_REGISTERED:
return "UUID used";
case TSS_E_KEY_NOT_LOADED:
return "the addressed key is currently not loaded";
default:
return "unknown error";
}
}

int main(int argc,char *argv)
{
TSS_RESULT result;
TSS_HTPM hTPM;
TSS_HCONTEXT hContext;
TSS_HPOLICY hownerpolicy,hSRKPolicy;
TSS_HKEY hSRK;
TSS_HKEY hkey,hkey2;
TSS_UUID SRK_UUID=TSS_UUID_SRK;
TSS_FLAG initFlags; //金鑰標記
TSS_UUID bindkeyUUID=TSS_UUID_USK1; //使用者的繫結金鑰

printf("建立上下文物件......\n");
result=Tspi_Context_Create(&hContext);
if(result!=TSS_SUCCESS)
{
printf("Context_Create ERROR:%s(%04x)\n",get_error(result),result);
}
result=Tspi_Context_Connect(hContext,NULL);
if(result!=TSS_SUCCESS)
{
printf("Context_Connect ERROR:%s(%04x)\n",get_error(result),result);
}

printf("建立TPM物件......\n");
result=Tspi_Context_GetTpmObject(hContext,&hTPM);
if(result!=TSS_SUCCESS)
{
printf("Tspi_Context_GetTpmObject ERROR:%s(%04x)\n",get_error(result),result);
}
result=Tspi_GetPolicyObject(hTPM,TSS_POLICY_USAGE,&hownerpolicy);
if(result!=TSS_SUCCESS)
{
printf("Tspi_GetPolicyObject ERROR:%s(%04x)\n",get_error(result),result);
}
result=Tspi_Policy_SetSecret(hownerpolicy,TSS_SECRET_MODE_POPUP,0,NULL);
if(result!=TSS_SUCCESS)
{
printf("Tspi_Policy_SetSecret ERROR:%s(%04x)\n",get_error(result),result);
}
printf("載入SRK金鑰......\n");
result=Tspi_Context_LoadKeyByUUID(hContext,TSS_PS_TYPE_SYSTEM,SRK_UUID,&hSRK);
if(result!=TSS_SUCCESS)
{
printf("Tspi_Context_LoadKeyByUUID ERROR:%s(%04x)\n",get_error(result),result);
}
printf("獲取SRK的策略物件......");
result=Tspi_GetPolicyObject(hSRK,TSS_POLICY_USAGE,&hSRKPolicy);
if(result!=TSS_SUCCESS)
{
printf("Tspi_GetPolicyObject ERROR:%s(%04x)\n",get_error(result),result);
}
printf("設定SRK的策略授權......");
result=Tspi_Policy_SetSecret(hSRKPolicy,TSS_SECRET_MODE_POPUP,0,NULL);
if(result!=TSS_SUCCESS)
{
printf("Tspi_Policy_SetSecret ERROR:%s(%04x)\n",get_error(result),result);
}
printf("建立繫結金鑰......\n");
initFlags=TSS_KEY_TYPE_BIND|TSS_KEY_SIZE_512|TSS_KEY_NO_AUTHORIZATION; //設定金鑰標記
result=Tspi_Context_CreateObject(hContext,TSS_OBJECT_TYPE_RSAKEY,initFlags,&hkey); //建立繫結金鑰
if(result!=TSS_SUCCESS)
{
printf("Tspi_Context_CreateObject ERROR:%s(%04x)\n",get_error(result),result);
}

printf("在TPM產生金鑰前,設定填充型別......\n");
result=Tspi_SetAttribUint32(hkey,TSS_TSPATTRIB_KEY_INFO,TSS_TSPATTRIB_KEYINFO_ENCSCHEME,TSS_ES_RSAESPKCSV15);
if(result!=TSS_SUCCESS)
{
printf("Tspi_SetAttribUint32 ERROR:%s(%04x)\n",get_error(result),result);
}
printf("產生金鑰,該金鑰不合PCR繫結\n");
result=Tspi_Key_CreateKey(hkey,hSRK,0);
if(result!=TSS_SUCCESS)
{
printf("Tspi_Key_CreateKey ERROR:%s(%04x)\n",get_error(result),result);
}

printf("裝載繫結金鑰到UUID......\n");
result=Tspi_Context_RegisterKey(hContext,hkey,TSS_PS_TYPE_USER,bindkeyUUID,TSS_PS_TYPE_SYSTEM,SRK_UUID);
if(result!=TSS_SUCCESS)
{
if(ERROR_CODE(result)==TSS_E_KEY_ALREADY_REGISTERED)
{
printf("UUID已被使用,登出此金鑰......\n");
result=Tspi_Context_UnregisterKey(hContext,TSS_PS_TYPE_USER,bindkeyUUID,&hkey);
if(result!=TSS_SUCCESS)
printf("UUID登出失敗 Tspi_Context_UnregisterKey ERROR :%s(%04x)\n",get_error(result),result);

result=Tspi_Context_RegisterKey(hContext,hkey,TSS_PS_TYPE_USER,bindkeyUUID,TSS_PS_TYPE_SYSTEM,SRK_UUID);
if(result!=TSS_SUCCESS)
printf("Tspi_Context_RegisterKey ERROR:%s(%04x)\n",get_error(result),result);
}
}
printf("SUCCESS!\n");
Tspi_Context_Close(hContext);
return 0;
}

9.2.2. 該程式實現的操作
建立上下文物件…
建立TPM物件…
載入SRK金鑰…
獲取SRK的策略物件…
設定SRK的策略授權…
建立繫結金鑰…
裝載繫結金鑰到UUID…

9.2.3. 編譯和執行
Tips:
要先啟動 tpmd 和 tcsd 程序,再執行測試程式的可執行檔案。

 

 遇到如下的錯誤:

Tspi_Key_CreateKey ERROR:persistentstoragetype is not valid/One or more parameters is incorrect(0003)

PS:解決後再更新???
————————————————
版權宣告:本文為CSDN博主「l龍貓先生l」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/CSDN_FengXingwei/article/details/89342797