這里先來看看安全驅動怎么設計。支持TruztZone技術的芯片可將某個特定外部設備配置成安全設備,使其只能被處于安全世界狀態(SWS)的ARM核訪問。如果要在OP-TEE中使用安全設備, 需要在OP-TEE OS中集成該安全設備的驅動程序 ,TA或OP-TEE OS可使用該安全驅動提供的接口來使用該安全設備。
要完成一個驅動的設計:向外暴露被調用的接口,將驅動集成。
在設計安全驅動的時候,先回顧一下,為什么可將某個特定外部設備配置成安全設備?
1、安全設備的硬件安全隔離
系統的外部設備一般是通過APB總線掛接到AXI總線上的,APB總線不支持ARM核對設備訪問時進行安全檢查的功能,故如果要將某個外部設備配置成安全設備,則需在SOC中添加TZPC組件和AXI-to-APB橋。
TZPC組件負責將某個特定外部設備配置成安全設備,并為該安全設備提供額外的安全信號, AXI-to-APB橋使用TZPC配置給該外部設備的安全信號來校驗ARM核發送的訪問請求中的安全狀態位(NS bit)是否與之匹配, 如果TZPC給外部設備提供的信號為安全信號而ARM核的訪問請求是在正常世界狀態(NWS)發起的,則AXI-to-APB總線會判定訪問失敗,從而實現系統對該外部設備的安全隔離。
TZPC組件主要有兩個作用,一是為TZMA提供安全區域大小配置信號,用于TZMA來配置片上SRAM、ROM安全區域的大小,另外一個作用是接入到AXI-to-APB總線上,為外部設備提供安全信號,將某個外部設備配置成安全設備。TZPC組件的信號連接圖如圖22-1所示。
TZPCR0SIZE信號線將被連接到TZMA組件上,用于TZMA配置片上SRAM、ROM安全區域的大小,
TZPCDECPROTx信號線將連接到AXI-to-APB橋上,用于配置某個外設是否為安全設備。
TZPC最多支持將24個外部設備設定為安全設備,且需將TZPC組件的寄存器地址設定在安全地址范圍內。
TZPC提供了18個寄存器,這些寄存器用于配置安全信號。這些寄存器的相關信息如表22-1所示。
通過配置TZPC組件寄存器的值可設定特定的安全信號的輸出組合,用于將外部設備設定成安全設備。
TZPC的基地址并不固定,但需確保TZPC的基地址是在安全地址區域中的。
知道這個安全驅動硬件是實現安全驅動的基礎,那么下一步就來看看怎么軟件實現安全驅動。
2、OP-TEE中安全驅動的框架
OP-TEE中的安全驅動是OP-TEE操作安全設備的載體。
TA通過調用某個安全驅動的接口就可實現對特定安全設備的操作。安全驅動在OP-TEE中的軟件框架如圖22-2所示。
(其實這里,你要搞清楚linux kernel與驅動的關系,那真的還是蠻簡單好理解的。但是我不知道~嚶嚶嚶) 系統服務層并非必需的,主要是為方便管理和上層使用。例如OP-TEE提供了各種各樣的密碼學算法,每一種算法的實現可通過不同的硬件引擎來完成。
為統一管理,可將這些硬件引擎驅動提供的操作接口統一集成到一個系統服務中,而上層用戶只需調用系統服務暴露的接口就可實現對硬件引擎的調用。(可能是通過輸入的參數進行分發)
下面展開講講這個框架的細節。
2.1 系統服務層
系統服務層在OP-TEE啟動過程中由initcall段的代碼進行初始化和啟動,一個系統服務的初始化函數則是通過使用service_init宏來進行定義并在編譯時鏈接到OP-TEE的鏡像文件中。
在編譯OP-TEE時,該初始化函數將被保存到OP-TEE鏡像文件的initcall段中。
至于系統服務的初始化函數所要執行的內容則由開發者自行決定,一般是在系統服務的初始化函數中進行該 服務的配置 、狀態量的初始化以及系統服務提供給上層調用的 操作接口變量的初始化 ,系統服務提供的結構體變量會包含 用于實現具體功能的函數指針變量 ,這些函數指針變量指向的函數就是安全驅動提供給TA調用的操作接口。
2.2 驅動層
OP-TEE啟動過程中會執行各安全驅動的初始化 ,驅動的初始化函數是在OP-TEE執行initcall段中的內容時被調用的,在OP-TEE中通過使用driver_init宏來告訴編譯器,在編譯時將driver_init宏傳入的函數作為某個驅動的入口函數保存在鏡像文件的initcall段中。
安全驅動的初始化主要用來完成安全設備的寄存器的配置以及私有數據的初始化。
如果某個安全驅動需要系統服務的配合,則還需要將驅動提供的操作接口連接到系統服務中的操作接口變量中。
若該驅動不需以系統服務的方式向上層提供操作接口,則不用將對應接口暴露給系統服務,而是由TA通過系統調用的方式直接調用安全驅動的接口來操作安全設備。
driver_init service_init
2.3 驅動文件在源代碼中的位置
安全驅動需要被編譯到OP-TEE鏡像文件中,OP-TEE中有專門的目錄來存放驅動和系統服務的源代碼。
將驅動編譯到OP-TEE鏡像文件之前還需修改對應的sub.mk文件,OP-TEE中保存驅動和系統服務源代碼的目錄對應關系如表22-2所示。
下面開始創建一個實例吧!
來看看基于上文的概念,創建一個安全驅動的流程是什么?
3、來整個栗子--安全驅動的開發過程和示例
在OP-TEE中,若需要使用系統服務的方式為上層TA提供操作接口,則一個完整的安全驅動需要實現TA接口部分、系統調用部分、系統服務部分、驅動實現部分。本節將結合實際的示例介紹這四部分的開發流程。
- TA接口部分
- 系統調用部分
- 系統服務部分
- 驅動實現部分
如果不使用系統服務,就少了一個步驟。
3.1 示例代碼獲取和集成
本示例中的驅動只實現了對內存的讀寫操作,并提供了測試使用的TA和CA。
讀者可使用如下指令從GitHub上獲取到示例源代碼:
git clone https://GitHub.com/shuaifengyun/opentee_driver.git
下載完代碼后就需要將該TA和CA集成到OP-TEE中,需修改OP-TEE源代碼build目錄下的qemu.mk(開發者板級對應的mk文件)和common.mk文件,同時也需要將安全驅動集成到OP-TEE的內核中。
然后編譯整體OP-TEE后就能夠使用該份示例代碼來驗證本書提供的安全驅動示例是否運行正常。
獲取到示例代碼后將opentee_driver/my_test目錄全部復制到op-tee的根目錄下,再切換到根目錄的build目錄中,然后使用git apply命令合入補丁文件后就可完成測試使用的TA和CA集成到OP-TEE,合入全部補丁的操作步驟如下:
1)將示例代碼中的my_test_common_3.0.0.patch文件和my_test_qemu_3.0.0.patch文件復制到build目錄中,將0001-Integrate-secure-driver-test-into-op-tee.patch文件復制到optee_os目錄中。
2)切換到build目錄,使用如下命令合入補?。?/p>
git apply my_test_common_3.0.0.patch
3)切換到optee_os目錄,使用如下命令合入安全驅動在內核中的補?。?/p>
git am 0001-Integrate-secure-driver-test-into-op-tee.patch
將補丁合入完成后就可使用make -f qemu.mk all編譯整個工程,然后使用make -f qemu.mk run-only來啟動OP-TEE,在啟動的正常世界狀態的終端執行secStorTest命令就能實現該示例的CA對TA的調用。示例代碼的運行效果如圖22-3所示。
3.2 驅動實現
開發一個安全驅動時,需要在optee_os/core/drivers目錄中建立該安全驅動的源文件,在源文件中實現驅動的初始化函數、操作設備的接口函數(read、write、ioctl),具體的接口函數由開發者自行定義。
若該驅動需要在系統啟動過程中執行一些初始化操作則可使用driver_init宏進行定義, 編譯完成后需要被執行的內容將會被保存到鏡像文件的initcall段中, 這些使用driver_init宏定義的內容將在OP-TEE啟動時被調用。 (相當于提前為驅動的調用準備了環境與初始條件)
示例源代碼中的driver_test.c文件需要放在optee_os/core/drivers目錄中,然后修改optee_os/core/drivers目錄下的sub.mk文件,將driver_test.c文件添加編譯系統中。在sub. mk文件中添加如下內容:
osrcs-y += driver_test.c
若需要使用宏的方式來控制該驅動的編譯,可將添加到sub.mk的內容修改成“srcs-$(CFG_XXX) += driver_test.c”,然后在optee_os/mk/config.mk文件中定義CFG_XXX變量,通過將CFG_XXX變量賦值成y或n來控制該驅動是否需要被編譯進系統。 (這個還是蠻有用的)
該驅動對應的頭文件driver_test.h文件需保存到optee_os/core/inlcude/drivers目錄中,該文件中聲明了該驅動暴露給外界調用的接口和相關結構體。
實現完驅動接口實現,現在來實現添加系統服務
3.3 添加系統服務
系統服務的添加不是必需的,為方便對底層驅動的管理和對外部設備的擴展,可將安全驅動的接口接入到某個系統服務中,通過系統服務向外界暴露調用接口,以便上層TA可以使用該安全驅動。
在本示例中建立的系統服務的源代碼為tee_test.c文件,需將該文件保存到optee_os/core/tee目錄中,同時將tee_test.h文件保存到optee_os/core/include/tee目錄中,然后修改optee_os/core/tee目錄中的sub.mk文件,添加“srcs-y += tee_test.c”,將tee_test.c集成到編譯系統中。
也可使用宏來控制該系統服務的編譯,其實現方法與上一節相同。
在tee_test.c文件中使用service_init宏來定義該系統服務的初始化函數(tee_test_init),該初始化函數將會被編譯到OP-TEE的初始化段中,OP-TEE啟動時將會執行服務段中包含的函數,調用tee_test_init函數初始化該系統服務。
到這里明白了driver_init和service_init的差異。一個是直接注冊驅動的系統調用,一個注冊到系統服務。
3.4 添加系統調用
上層的TA運行于OP-TEE的用戶空間,如果上層的TA需要調用安全驅動,則需通過調用系統調用接口的方式來調用安全驅動提供的操作接口。
若要在TA中使用本示例中的安全驅動,則還需在OP-TEE中增加該驅動對應的系統調用。包括用戶空間接口的定義和內核空間接口的定義,關于OP-TEE中系統調用的實現原理可參閱第16章。(小的馬上后面補上)
1.用戶空間代碼的修改
修改optee_os/lib/libutee/arch/arm/utee_syscalls_asm.S文件,添加如下內容:
UTEE_SYSCALL utee_testDriver_write, TEE_SCN_TESTDRIVER_WRITE, 3
utee_testDriver_xxx是在TA中調用該驅動時使用的函數,
TEE_SCN_TESTDRIVER_XXX是該系統調用對應的索引值。
上層TA調用utee_testDriver_xxx函數后會進入OP-TEE的內核空間,系統通過查找TEE_SCN_TESTDRIVER_XXX對應的接口來找到該功能在OP-TEE內核中的實現。
最后的數字表示調用該接口時需要代入的參數的個數。
修改optee_os/lib/libutee/include/utee_syscalls.h文件,添加如下內容,申明上述三個函數接口。在TA的源代碼中包含該頭文件后就可調用這三個接口來對該安全驅動進行調用。
TEE_Result utee_testDriver_write(void *buf, size_t blen, size_t offset);
修改optee_os/lib/libutee/include/tee_syscall_numbers.h文件,添加上述三個系統調用接口的索引值,并修改TEE_SCN_MAX的值,需要修改和添加的內容如下:
#define TEE_SCN_TESTDRIVER_WRITE 71
2.內核空間代碼的修改
修改optee_os/core/arch/arm/tee/arch_svc.c文件中系統調用數組變量tee_svc_syscall_table的內容,將上述系統調用對應的內核層接口添加到該數組中,并包含申明這三個接口的頭文件,在該文件中添加的內容如下:
SYSCALL_ENTRY(syscall_testDriver_write),
上述三個函數的具體實現在tee_test.c文件中,讀者可自行查閱這三個接口函數的實現。
3.5 測試使用的TA和CA
將該示例的測試TA和CA添加到OP-TEE中需要修改讀者開發環境對應的mk文件中。以使用QEMU方式運行OP-TEE為例,則需要修改qemu.mk文件添加該示例代碼的編譯目標,修改步驟如下:
1)添加my_test的編譯目標:
############################################################################
# secure driver test TA--my_test
############################################################################
my_test: my_test-common
my_test-clean: my_test-clean-common
2)將my_test和my_test-clean添加到全局的all和clean目標依賴關系中:
all: bios-qemu qemu soc-term optee-examples my_test
clean: bios-qemu-clean busybox-clean linux-clean optee-os-clean
optee-client-clean qemu-clean soc-term-clean check-clean
optee-examples-clean my_test-clean
添加部分的主要作用是定義my_test目標并建立該編譯目標與all的依賴關系,在編譯整個OP-TEE工程時會被使用到。修改完板級編譯的mk文件后,還需修改build/common.mk文件。修改的內容主要是將my_test的編譯目標集成到系統編譯中,需要修改的內容如下:
1)定義my_test路徑變量:
MY_TEST_PATH ? = $(ROOT)/my_test
2)添加my_test的目標依賴,修改filelist-tee-common目標的依賴關系如下:
filelist-tee-common: optee-client xtest optee-examples my_test
3)增加TA和CA的common目標:
############################################################################
# my_test
###########################################################################
MY_TEST_COMMON_FLAGS ? = HOST_CROSS_COMPILE=$(CROSS_COMPILE_NS_USER)
TA_CROSS_COMPILE=$(CROSS_COMPILE_S_USER)
TA_DEV_KIT_DIR=$(OPTEE_OS_TA_DEV_KIT_DIR)
TEEC_EXPORT=$(OPTEE_CLIENT_EXPORT)
.PHONY: my_test-common
my_test-common: optee-os optee-client
$(MAKE) -C $(MY_TEST_PATH) $(MY_TEST_COMMON_FLAGS)
MY_TEST_CLEAN_COMMON_FLAGS ? = TA_DEV_KIT_DIR=$(OPTEE_OS_TA_DEV_KIT_DIR)
.PHONY: my_test-clean-common
my_test-clean-common:
$(MAKE) -C $(MY_TEST_PATH) $(MY_TEST_CLEAN_COMMON_FLAGS) clean
4)添加clean操作的依賴關系:
optee-os-clean-common: xtest-clean optee-examples-clean my_test-clean
5)在filelist-tee-common中添加TA和CA鏡像需要被打包到文件系統中的操作:
@echo“#secure driver test TA“ > > $(fl)
@if [ -e $(MY_TEST_PATH)/host/my_test ]; then
echo "file /bin/my_test"
"$(MY_TEST_PATH)/host/my_test 755 0 0" > > $(fl);
echo "file /lib/optee_armtz/9269fadd-99d5-4afb-a1dc-ee3e9c61b04c.ta"
"$(MY_TEST_PATH)/ta/9269fadd-99d5-4afb-a1dc-ee3e9c61b04c.ta 444 0 0"
> > $(fl);
fi
2.4 安全驅動示例的測試
完成所有修改之后,編譯整個OP-TEE工程然后運行。在OP-TEE的啟動日志中能看見示例中的系統服務和驅動啟動的日志,啟動的日志如圖22-4所示。
系統啟動后,在REE側的終端中輸入對應的指令就可通過TA調用到該示例的安全驅動,指令說明如下。
1.向驅動中寫入數據
my_test writeDev [offset] [len]
offset:表示需將數據寫入驅動提供的buffer中的偏移位置。
len:表示需要寫入驅動中數據的長度。寫入驅動中的數據在CA源代碼中被設定,讀者可通過修改CA源代碼中g_WriteData變量中的值將不同的內容寫入該安全驅動中。
2.讀取驅動中的數據
my_test readDev [offset] [len]
offset:表示從驅動中buffer的哪個位置開始讀取。
len:表示需要從驅動中讀取的內容長度。
3.打印出驅動中的數據
my_test dumpDev [len]
len:表示需要打印的數據的長度。
用于測試添加的模擬安全驅動的TA和CA運行的效果如圖22-5所示。
小結一下啦
前輩的《手機安全和可信應用開發指南》確實寫的很好啊,但是這里估計有linux的驅動開發經歷,會更加深映像一些。這個part的學習解決了我的一些問題。
一起學習了OP-TEE中安全設備驅動的開發以及實現安全設備的安全隔離的原理。
當需要在系統中增加安全設備時,除了需在OP-TEE中開發該設備對應的安全驅動之外,還需修改TZPC的配置為該設備提供安全信號。
TA通過調用系統調用接口的方式陷入OP-TEE的內核空間來使用驅動,如需對多個安全設備進行統一管理,則可添加一個系統服務,將各安全驅動提供的接口集成到該系統服務中,使該系統服務封裝接口暴露給上層使用。
-
驅動器
+關注
關注
51文章
7436瀏覽量
143315 -
寄存器
+關注
關注
30文章
5106瀏覽量
117975 -
狀態機
+關注
關注
2文章
486瀏覽量
27228 -
SRAM控制器
+關注
關注
0文章
11瀏覽量
5864
發布評論請先 登錄
相關推薦
評論