手機安全和可信應用開發(fā)指南.pdf
http://www.www.srpcoatings.com
2020年1月8日
![]() |
| 第1頁 |
![]() |
| 第6頁 |
![]() |
| 第14頁 |
![]() |
| 第24頁 |
![]() |
| 第45頁 |
![]() |
| 第408頁 |
參見附件(18090KB,786頁)。
手機安全和可信應用開發(fā)指南,這是一本技術開發(fā)教程書籍,里面的內容由基礎到深入的為學者們講解,全書一共四大篇三四十個小章節(jié),有需要的同學可以學習。

內容提要
TrustZone技術是一種提高ARM芯片安全性的技術,OP-TEE是基于ARM的TrustZone技術搭建的可信執(zhí)行環(huán)境。兩者的結合可為系統(tǒng)軟件提供硬件級別的安全保護。本書主要分為4篇,總計25章,第壹篇介紹了TrustZone技術的背景、實現原理、系統(tǒng)基本框架以及OP-TEE開發(fā)環(huán)境的搭建;第二篇分析了OP-TEE在REE和TEE中各組件的作用和聯(lián)系,為將OP-TEE集成到基于ARMv7/ARMv8處理器的開發(fā)平臺打下基礎;第三篇詳細介紹OP-TEE內核的中斷處理、線程管理和通信等主要功能的實現原理,使讀者對TEEOS的架構設計有進一步的認識;第四篇介紹基于OP-TEE在加密、解密、安全存儲、在線支付等方面的實際應用,以及如何開發(fā)基于OP-TEE的可信應用程序和安全驅動軟件。
部分目錄
第一篇 基礎技術篇
第1章 可信執(zhí)行環(huán)境
1.1 系統(tǒng)存在的安全問題
1.2 TEE如何保護數據安全
1.3 現有TEE解決方案
1.3.1 智能手機領域的TEE
1.3.2 智能電視領域的TEE
1.3.3 IoT領域及其他領域的TEE
1.4 為什么選擇OP-TEE
第2章 ARM的TrustZone技術
2.1 TrustZone技術
2.1.1 片上系統(tǒng)硬件框架
2.1.2 ARMv7架構的TrustZone技術
2.1.3 ARMv8架構的TrustZone技術
2.2 ARM安全擴展組件
2.2.1 AXI總線上安全狀態(tài)位的擴展
2.2.2 AXI-to-APB橋的作用
2.2.3 TrustZone地址空間控制組件
2.2.4 TrustZone內存適配器組件
2.2.5 TrustZone保護控制器組件
2.2.6 TrustZone中斷控制器組件
2.2.7 Cache和MMU的擴展
2.3 TrustZone技術對資源隔離的實現
2.3.1 中斷源的隔離
2.3.2 片上RAM和片上ROM的隔離
2.3.3 片外DRAM的隔離
2.3.4 外圍設備的隔離
2.4 小結
第3章 ARM可信固件
3.1 為什么使用ATF
3.2 ATF的主要功能
3.3 ATF與TEE的關系
3.4 小結
第4章 OP-TEE運行環(huán)境的搭建及編譯
4.1 獲取OP-TEE代碼并搭建運行環(huán)境
4.1.1 OP-TEE開發(fā)環(huán)境的搭建
4.1.2 獲取OP-TEE的源代碼
4.1.3 獲取編譯OP-TEE的toolchain
4.1.4 編譯QEMU
4.1.5 運行OP-TEE
4.1.6 運行xtest和optee_example_hello_world
4.2 運行CA和TA示例
4.2.1 示例代碼的獲取和集成
4.2.2 目錄和文件創(chuàng)建
4.2.3 CA端代碼的修改
4.2.4 TA端代碼的修改
4.2.5 TA和CA在OP-TEE的集成
4.3 OP-TEE源代碼結構
4.4 OP-TEE編譯
4.4.1 編譯目標的依賴關系
4.4.2 bios.bin鏡像的生成過程
4.4.3 run-only目標的執(zhí)行
4.5 小結
第二篇 系統(tǒng)集成篇
第三篇 OP-TEE內核篇
第四篇 應用開發(fā)篇
此的特色
俗話說,基礎打不牢,學問攀不高。本書采取自下而上的方式從硬件的角度介紹了TrustZone技術,并結合源代碼逐步剖析了基于TrustZone技術的OP-TEE實現。在技術深度上,本書從入門者的角度出發(fā)由淺入深,從最基礎的開發(fā)環(huán)境的搭建到最終的OP-TEE OS的內部實現都進行了介紹;從內容易讀性上來講,本書提供了基礎的示例代碼和各種算法的使用示例,并給出了所有示例的源代碼鏈接及操作的實驗步驟。相信讀者通過邊學習邊實踐的方式閱讀完本書后,能夠掌握TrustZone技術的基礎原理和使用OP-TEE進行實際的應用開發(fā)。
由于任何TEE方案的源代碼都屬于芯片廠商的商業(yè)機密,外界無法一覽各TEE方案的實現原理,且TrustZone也是最近幾年才被正式商用的,所以網上的資料較少。本書是作者基于多年的工作積累并對實際工作過程中遇見的問題進行整理后形成的。
手機安全和可信應用開發(fā)指南截圖


網絡空間安全技術叢書
手機安全和可信應用開發(fā)指南:TrustZone
與OP-TEE技術詳解
帥峰云 黃騰 宋洋 編著
ISBN:978-7-111-60956-8
本書紙版由機械工業(yè)出版社于2018年出版,電子版
由華章分社(北京華章圖文信息有限公司,北京奧
維博世圖書發(fā)行有限公司)全球范圍內制作與發(fā)
行。
版權所有,侵權必究
客服熱線:+ 86-10-68995265
客服信箱:service@bbbvip.com
官方網址:www.hzmedia.com.cn
新浪微博 @華章數媒
微信公眾號 華章電子書(微信號:hzebook)目錄 推薦序
前言
致謝
第一篇 基礎技術篇
第1章 可信執(zhí)行環(huán)境
1.1 系統(tǒng)存在的安全問題
1.2 TEE如何保護數據安全
1.3 現有TEE解決方案
1.3.1 智能手機領域的TEE
1.3.2 智能電視領域的TEE
1.3.3 IoT領域及其他領域的TEE
1.4 為什么選擇OP-TEE
第2章 ARM的TrustZone技術
2.1 TrustZone技術
2.1.1 片上系統(tǒng)硬件框架
2.1.2 ARMv7架構的TrustZone技術
2.1.3 ARMv8架構的TrustZone技術
2.2 ARM安全擴展組件
2.2.1 AXI總線上安全狀態(tài)位的擴展
2.2.2 AXI-to-APB橋的作用
2.2.3 TrustZone地址空間控制組件
2.2.4 TrustZone內存適配器組件
2.2.5 TrustZone保護控制器組件
2.2.6 TrustZone中斷控制器組件2.2.7 Cache和MMU的擴展
2.3 TrustZone技術對資源隔離的實現
2.3.1 中斷源的隔離
2.3.2 片上RAM和片上ROM的隔離
2.3.3 片外DRAM的隔離
2.3.4 外圍設備的隔離
2.4 小結
第3章 ARM可信固件
3.1 為什么使用ATF
3.2 ATF的主要功能
3.3 ATF與TEE的關系
3.4 小結
第4章 OP-TEE運行環(huán)境的搭建及編譯
4.1 獲取OP-TEE代碼并搭建運行環(huán)境
4.1.1 OP-TEE開發(fā)環(huán)境的搭建
4.1.2 獲取OP-TEE的源代碼
4.1.3 獲取編譯OP-TEE的toolchain
4.1.4 編譯QEMU
4.1.5 運行OP-TEE
4.1.6 運行xtest和
optee_example_hello_world
4.2 運行CA和TA示例
4.2.1 示例代碼的獲取和集成
4.2.2 目錄和文件創(chuàng)建
4.2.3 CA端代碼的修改
4.2.4 TA端代碼的修改4.2.5 TA和CA在OP-TEE的集成
4.3 OP-TEE源代碼結構
4.4 OP-TEE編譯
4.4.1 編譯目標的依賴關系
4.4.2 bios.bin鏡像的生成過程
4.4.3 run-only目標的執(zhí)行
4.5 小結
第二篇 系統(tǒng)集成篇
第5章 QEMU運行OP-TEE的啟動過程
5.1 bios.bin的入口函數
5.2 OP-TEE鏡像的加載和啟動
5.3 Linux內核鏡像的加載和啟動
5.4 rootfs的掛載
5.5 OP-TEE驅動的啟動
5.6 tee_supplicant的啟動
5.7 小結
第6章 安全引導功能及ATF的啟動過程
6.1 安全引導的作用
6.2 安全引導的原理
6.2.1 ARMv7安全引導的過程
6.2.2 ARMv8安全引導的過程
6.3 ATF的啟動過程
6.3.1 ATF中bl1的啟動
6.3.2 ATF中bl2的啟動
6.3.3 ATF中bl31的啟動
6.3.4 ATF中bl32的啟動6.3.5 ATF啟動過程小結
6.4 小結
第7章 OP-TEE OS的啟動過程
7.1 OP-TEE鏡像啟動過程
7.1.1 OP-TEE OS的入口函數
7.1.2 OP-TEE的內核初始化過程
7.1.3 OP-TEE服務項的啟動
7.1.4 OP-TEE驅動的掛載
7.2 ARM64位與ARM32位OP-TEE啟動過程的
差異
7.3 小結
第8章 OP-TEE在REE側的上層軟件
8.1 OP-TEE的軟件框架
8.2 REE側libteec庫提供的接口
8.2.1 libteec庫提供的接口說明
8.2.2 CA調用libteec庫中接口的流程
8.3 REE側的守護進程——tee_supplicant
8.3.1 tee_supplicant編譯生成和自啟動
8.3.2 tee_supplicant入口函數
8.3.3 tee_supplicant存放RPC請求的結構體
8.3.4 tee_supplicant中的無限循環(huán)
8.3.5 tee_supplicant獲取TA的RPC請求
8.3.6 TA RPC請求的解析
8.3.7 RPC請求的處理
8.3.8 回復RPC請求
8.4 各種RPC請求的處理8.4.1 加載TA鏡像
8.4.2 操作REE側的文件系統(tǒng)
8.4.3 操作RPMB
8.4.4 分配共享內存
8.4.5 釋放共享內存
8.4.6 記錄程序執(zhí)行效率
8.4.7 網絡套接字操作
8.5 小結
第9章 REE側OP-TEE的驅動
9.1 OP-TEE驅動模塊的編譯保存
9.2 REE側OP-TEE驅動的加載
9.2.1 設備號和class的初始化
9.2.2 optee_driver_init函數
9.2.3 掛載驅動的probe操作
9.2.4 獲取切換到Monitor模式或EL3的接口
9.2.5 驅動版本和API版本校驗
9.2.6 判定OP-TEE是否預留共享內存空間
9.2.7 配置驅動與OP-TEE之間的共享內存
9.2.8 分配和設置tee0和teepriv0的設備信息
結構體變量
9.2.9 tee0和teepriv0設備的注冊
9.2.10 請求隊列的初始化
9.2.11 使能TEE中共享內存的緩存
9.2.12 OP-TEE驅動掛載的總結
9.3 REE側用戶空間對驅動的調用過程
9.4 OP-TEE驅動中重要的結構體變量9.4.1 OP-TEE驅動的file_operation結構體變
量tee_fops
9.4.2 tee0設備的tee_driver_ops結構體變量
optee_ops
9.4.3 teepriv0設備的操作結構體變量
optee_supp_ops
9.4.4 共享驅動緩存操作變量
tee_shm_dma_buf_ops
9.5 OP-TEE驅動與OP-TEE之間共享內存的注
冊和分配
9.6 libteec庫中的接口在驅動中的實現
9.6.1 libteec庫中的open操作
9.6.2 libteec庫中的release操作
9.6.3 libteec執(zhí)行get_version操作
9.6.4 libteec庫中的open session操作
9.6.5 libteec庫中的invoke操作
9.7 tee_supplicant接口在驅動中的實現
9.7.1 接收OP-TEE的RPC請求
9.7.2 獲取OP-TEE的RPC請求
9.7.3 OP-TEE的RPC請求的返回
9.8 小結
第三篇 OP-TEE內核篇
第10章 ARM核安全態(tài)和非安全態(tài)間的切換
10.1 ARMv7基本知識
10.1.1 ARMv7運行模式擴展
10.1.2 安全狀態(tài)位擴展10.1.3 重要寄存器
10.1.4 安全監(jiān)控模式調用的匯編指令
10.2 Monitor模式下的處理過程
10.2.1 Monitor模式對安全監(jiān)控模式調用的
處理
10.2.2 正常世界狀態(tài)中觸發(fā)安全監(jiān)控模式
調用的處理過程
10.2.3 安全世界狀態(tài)中觸發(fā)安全監(jiān)控模式
調用的處理過程
10.3 ARMv8基本知識
10.3.1 ARM核運行模式的新定義
10.3.2 ARMv8安全狀態(tài)位擴展
10.3.3 寄存器資源
10.3.4 安全監(jiān)控模式調用匯編指令
10.4 EL3的處理過程
10.4.1 ATF中EL3異常向量表的注冊
10.4.2 EL3處理安全監(jiān)控模式調用的流程
10.4.3 安全世界狀態(tài)中觸發(fā)安全監(jiān)控模式
調用的處理過程
10.4.4 正常世界狀態(tài)中觸發(fā)安全監(jiān)控模式
調用的處理過程
10.4.5 opteed_smc_handler函數
10.5 小結
第11章 OP-TEE對安全監(jiān)控模式調用的處理
11.1 OP-TEE的線程向量表
11.2 ARMv7中Monitor模式對安全監(jiān)控模式調用的處理
11.3 ARMv8中EL3處理安全監(jiān)控模式調用的
實現
11.4 OP-TEE對快速安全監(jiān)控模式調用的處理
11.5 OP-TEE對標準安全監(jiān)控模式調用的處理
11.5.1 OP-TEE對RPC請求返回操作的處理
11.5.2 OP-TEE對libteec庫觸發(fā)的安全監(jiān)控
模式調用的處理
11.6 小結
第12章 OP-TEE對中斷的處理
12.1 系統(tǒng)的中斷處理
12.2 中斷控制器
12.2.1 GIC寄存器
12.2.2 ARMv7 SCR寄存器的設定
12.2.3 ARMv8 SCR寄存器的設定
12.2.4 GICv2架構
12.2.5 GICv3架構
12.3 異常向量表配置
12.3.1 ARMv7中Monitor模式的異常向量表
12.3.2 ARMv8中EL3階段的異常向量表
12.3.3 OP-TEE異常向量的配置
12.4 OP-TEE的線程向量表
12.5 全局handle變量的初始化
12.6 ARMv7 Monitor對FIQ事件的處理
12.7 ARMv8 EL3階段對FIQ事件的處理
12.8 OP-TEE對FIQ事件的處理12.9 OP-TEE對IRQ事件的處理
12.10 小結
第13章 OP-TEE對TA操作的各種實現
13.1 創(chuàng)建會話在OP-TEE中的實現
13.1.1 靜態(tài)TA的創(chuàng)建會話操作
13.1.2 動態(tài)TA的創(chuàng)建會話操作
13.2 調用TA命令操作在OP-TEE中的實現
13.2.1 靜態(tài)TA的調用命令操作的實現
13.2.2 動態(tài)TA的調用命令操作實現
13.3 關閉會話操作在OP-TEE中的實現
13.3.1 靜態(tài)TA的關閉會話操作
13.3.2 動態(tài)TA的關閉會話操作
13.4 小結
第14章 OP-TEE的內存和緩存管理
14.1 物理內存和緩存數據的硬件安全保護
14.1.1 內存設備安全區(qū)域的隔離
14.1.2 MMU和緩存中數據的安全隔離
14.2 ARM核對內存的訪問
14.2.1 ARM核獲取內存數據的過程
14.2.2 獲取緩存數據的過程
14.2.3 緩存和TLB中條目的一致性
14.3 OP-TEE對內存區(qū)域的管理
14.3.1 OP-TEE中內存區(qū)域的類型
14.3.2 內存區(qū)域編譯設置
14.4 MMU的初始化和映射頁表
14.4.1 MMU的初始化入口函數14.4.2 物理地址到虛擬地址表的建立
14.4.3 MMU轉換頁表的創(chuàng)建
14.4.4 MMU寄存器配置
14.5 OP-TEE內存安全權限檢查
14.6 系統(tǒng)的共享內存
14.6.1 共享內存的配置
14.6.2 OP-TEE驅動與OP-TEE之間的共享
內存
14.6.3 OP-TEE內核空間與用戶空間之間的
共享內存
14.7 數據是否需要寫入Cache
14.8 小結
第15章 OP-TEE中的線程管理
15.1 OP-TEE中的線程
15.2 線程狀態(tài)切換
15.2.1 Free態(tài)到Active態(tài)的實現
15.2.2 Active態(tài)到Suspend態(tài)的實現
15.2.3 Suspend態(tài)到Active態(tài)的實現
15.2.4 Active態(tài)到Free態(tài)的實現
15.3 線程運行時的資源
15.3.1 線程數據結構體
15.3.2 OP-TEE分配的內核棧
15.3.3 線程運行于用戶空間的資源
15.3.4 tee_ta_session結構體
15.4 線程運行時資源的使用關系
15.5 OP-TEE中線程的調度15.6 線程的死鎖
15.6.1 死鎖的原理
15.6.2 防止死鎖
15.7 小結
第16章 OP-TEE的系統(tǒng)調用
16.1 OP-TEE系統(tǒng)調用的作用
16.2 OP-TEE系統(tǒng)調用的實現
16.2.1 系統(tǒng)調用的整體流程
16.2.2 系統(tǒng)調用的定義
16.2.3 系統(tǒng)調用表tee_sv_syacall_table
16.3 小結
第17章 OP-TEE的IPC機制
17.1 IPC機制的作用
17.2 IPC機制的原理
17.3 IPC的實現
17.3.1 TA調用其他TA的實現
17.3.2 TA調用系統(tǒng)服務和安全驅動的實現
17.3.3 TA對密碼學系統(tǒng)服務的調用實現
17.3.4 對SE功能模塊進行操作的系統(tǒng)服務
17.3.5 加載TA鏡像的系統(tǒng)服務
17.4 小結
第四篇 應用開發(fā)篇
第18章 TA鏡像的簽名和加載
18.1 TA鏡像文件的編譯和簽名
18.1.1 TA鏡像文件的編譯
18.1.2 對TA鏡像文件的簽名18.2 TA鏡像的加載
18.2.1 REE側獲取TA鏡像文件的內容
18.2.2 加載TA鏡像的RPC請求
18.2.3 RPC請求的發(fā)送
18.2.4 讀取TA鏡像文件內容到共享內存
18.3 TA鏡像合法性的驗證
18.3.1 驗證TA鏡像合法性使用的RSA公鑰
的產生和獲取
18.3.2 TA鏡像文件合法性的檢查
18.4 加載TA鏡像到OP-TEE的用戶空間
18.5 TA運行上下文的初始化
18.6 小結
第19章 OP-TEE中的密碼學算法
19.1 算法使用示例
19.1.1 示例代碼獲取和集成
19.1.2 板級編譯文件的修改
19.1.3 通用編譯文件的修改
19.1.4 編譯運行
19.2 OP-TEE中的SHA算法
19.2.1 TA中使用SHA算法的實現
19.2.2 SHA算法實現接口說明
19.3 OP-TEE中的AES算法
19.3.1 TA中使用AES算法的實現
19.3.2 AES算法實現接口說明
19.4 OP-TEE中的RSA算法
19.4.1 TA中使用RSA算法的實現19.4.2 RSA算法實現接口說明
19.5 小結
第20章 OP-TEE的安全存儲
20.1 安全存儲簡介
20.2 安全存儲使用示例
20.2.1 示例代碼獲取和集成
20.2.2 板級編譯文件的修改
20.2.3 通用編譯文件的修改
20.2.4 編譯運行
20.3 安全存儲功能使用的密鑰
20.3.1 安全存儲密鑰
20.3.2 可信應用的存儲密鑰
20.3.3 文件加密密鑰
20.4 安全文件、dirf.db文件的數據格式和操
作過程
20.4.1 dirf.db文件和安全文件的格式
20.4.2 安全存儲功能中使用的重要結構體
20.4.3 安全存儲中的文件節(jié)點組成
20.4.4 查詢安全文件中的特定數據塊
20.5 安全存儲文件的創(chuàng)建
20.5.1 安全存儲軟件框架
20.5.2 dirf.db文件的創(chuàng)建
20.5.3 安全文件的創(chuàng)建
20.6 安全文件的打開操作
20.6.1 安全文件的打開
20.6.2 打開dirf.db文件并建立節(jié)點樹20.6.3 安全文件在datatee目錄下的文件編
號
20.6.4 打開特定安全文件
20.7 安全文件的讀寫操作
20.7.1 安全文件中數據的讀取
20.7.2 安全文件中數據的寫入
20.8 安全文件中數據的加解密
20.8.1 各種類型數據的組成及作用
20.8.2 元數據的加密
20.8.3 數據塊區(qū)域的加密策略
20.9 小結
第21章 可信應用及客戶端應用的開發(fā)
21.1 TA及CA的基本概念
21.2 GP標準
21.3 GP標準對TA屬性的定義
21.4 GP標準定義的接口
21.4.1 GP定義的客戶端接口
21.4.2 GP定義的內部接口
21.5 TA和CA的實現
21.5.1 建立CA和TA的目錄結構
21.5.2 CA代碼的實現
21.5.3 TA代碼的實現
21.6 TA和CA的集成
21.6.1 CA和TA的Makefile的修改
21.6.2 OP-TEE中comm.mk和xxx.mk文件的
修改21.7 TA和CA的調試
21.8 TA和CA的使用
21.9 小結
第22章 安全驅動的開發(fā)
22.1 安全設備的硬件安全隔離
22.2 OP-TEE中安全驅動的框架
22.2.1 系統(tǒng)服務層
22.2.2 驅動層
22.2.3 驅動文件在源代碼中的位置
22.3 安全驅動的開發(fā)過程和示例
22.3.1 示例代碼獲取和集成
22.3.2 驅動實現
22.3.3 添加系統(tǒng)服務
22.3.4 添加系統(tǒng)調用
22.3.5 測試使用的TA和CA
22.4 安全驅動示例的測試
22.5 小結
第23章 終端密鑰在線下發(fā)系統(tǒng)
23.1 密鑰在線下發(fā)系統(tǒng)的框架
23.2 密鑰在線下發(fā)的數據包格式
23.3 密鑰在線下發(fā)系統(tǒng)示例
23.3.1 示例代碼獲取和集成
23.3.2 板級編譯文件的修改
23.3.3 通用編譯文件的修改
23.3.4 編譯運行
23.4 離線工具的使用23.5 小結
第24章 基于OP-TEE的在線支付系統(tǒng)
24.1 在線支付系統(tǒng)的基本框架
24.2 可信通信通道
24.3 數據交互協(xié)議
24.3.1 數據頭部區(qū)域
24.3.2 數據區(qū)域
24.3.3 電子簽名區(qū)域
24.3.4 交互數據包的格式
24.4 在線支付系統(tǒng)示例的實現
24.4.1 第一次握手請求
24.4.2 第二次握手數據的解析
24.4.3 第三次握手請求
24.4.4 支付請求
24.4.5 支付反饋
24.5 示例的集成
24.5.1 示例代碼的獲取和集成
24.5.2 板級編譯文件的修改
24.5.3 通用編譯文件的修改
24.5.4 編譯運行
24.5.5 示例支持的命令說明
24.5.6 服務器端工具
24.6 組包操作嵌入內核
24.7 支付系統(tǒng)與生物特征的結合
24.8 小結
第25章 TEE可信應用的使用領域25.1 在線支付
25.2 數字版權保護
25.3 身份驗證
25.4 其他領域
術語表推薦序
近年來隨著指紋支付的盛行,如支付寶、微信
支付等,可信執(zhí)行環(huán)境(Trusted Execution
Environment,TEE)被廣泛應用在手機、平板電腦
等移動終端設備中。尤其是近年來谷歌對系統(tǒng)安全
問題越來越重視,可信執(zhí)行環(huán)境已成為谷歌提升系
統(tǒng)安全性的重要技術之一,包含為人熟知的
keymaster、gatekeeper等,未來在Android P上還會
引入基于TUI(Trusted User Interface)衍生的
Confirmation UI,這將會為使用者提供更好的安全
體驗。
可信執(zhí)行環(huán)境是一個典型的軟硬件協(xié)同合作的
概念,基于ARM的TrustZone技術為系統(tǒng)提供資源
的物理隔離,將系統(tǒng)執(zhí)行環(huán)境區(qū)隔為安全區(qū)域和非
安全區(qū)域。開發(fā)者通過使用安全操作系統(tǒng)(secure
OS)提供的API開發(fā)更多的可信應用來實現特定的
安全功能。系統(tǒng)的安全是環(huán)環(huán)相扣的信任鏈,從設
備開機的安全引導到安全操作系統(tǒng)的安全性驗證,一直到軟件開發(fā)者開發(fā)的軟件安全性驗證,每層相
扣,而可信執(zhí)行環(huán)境為可信應用提供了一個基礎且
可信任的執(zhí)行環(huán)境。
未來TEE的發(fā)展方向是多元的,TEE的應用也會進入更多的產業(yè),除了目前大熱的指紋識別之
外,系統(tǒng)也會引入更多的生物識別技術,如虹膜與
人臉識別,從攝像頭獲取圖像到識別演算的整個過
程都會在TEE中完成。此外TUI也是重要的方向之
一,使用者如何確認所見即所支付,確認的支付金
額或轉賬賬號不會被別人攻擊或修改,都是相當重
要的安全需求。除了移動終端設備之外,車載系統(tǒng)
和IoT設備也都有對應的安全需求,因此在可遇見
的未來,TEE將會被廣泛應用到不同領域、不同的
電子設備中。
此外,安全應用的開發(fā)者如何將安全應用廣泛
部署到不同的設備中,以及如何安全升級它們也相
當重要。當發(fā)現了軟件漏洞,如何第一時間更新安
全應用并避免版本回滾的攻擊,是系統(tǒng)安全的一個
重要議題,目前商用TEE的生態(tài)、安全應用的簽名
密鑰都掌握在設備制造商手中,而安全應用的獨立
在線下發(fā)和更新,將是未來的重要技術發(fā)展方向。
機緣巧合,我認識峰云已經有相當久的時間
了,他對TEE的了解相當深入,也相當用心地完成
了該書,遇到有疑問與不理解的地方,他會想方設
法地找出答案,他的專業(yè)與用心深受大家的肯定與
贊賞。本書涵蓋了TEE的硬件和軟件知識,通過
OP-TEE開源項目的協(xié)助,讀者可以通過理論與實
踐的結合,深入理解TEE的原理、設計與應用。期望通過本書的出版,能夠讓更多人了解與接觸TEE
的相關知識,進而發(fā)現更多的應用場景,享受更多
的安全服務,讓未來的生活在因為科技更方便的同
時,使用者的隱私與安全也能得到保護。
邱國政(Koshi)
Trustonic中國OEM經理前言
早在2014年,投資過Facebook、Skype、Twitter等的風投公司創(chuàng)始人安德森就說:“移動正
在吞噬這個世界”(mobile is eating the world)。這
毫不夸張,全球范圍內移動設備的數量已經超過了
世界人口的總和。在如今信息化技術高速發(fā)展的時
代,人們的生活越來越離不開智能手機,越來越多
的業(yè)務從原先復雜的流程演變到現在只需要簡單地
在手機上按幾個按鍵。技術是一把雙刃劍,總能給
人帶來難以想象的便利,但便利總是伴隨著用戶隱
私的泄漏、身份認證的濫用等一系列的安全風險。
據著名安全漏洞報告機構FreeBuf 2017年度移動應
用程序安全漏洞與數據泄漏狀況報告指出,多達
88%的金融類App存在內存敏感數據泄漏問題,娛
樂類移動應用程序更是安全漏洞的重災區(qū),社交類
App被仿冒的概率比其他類別平均高出10倍以上。
如何保障移動設備的安全,提高安全認證程序的可
靠性,一直是近幾年的熱門話題。
由嵌入式處理器最大的設計商ARM公司提出
的硬件虛擬化擴展技術TrustZone,發(fā)展到現在已經
有十余年的光景,如今已成為智能手機平臺不可或
缺的部分。從Android 7.0開始,谷歌就明確表示,Android設備上有關生物特征(指紋、虹膜等)識別的方案一定要基于可信執(zhí)行環(huán)境(Trust
Execution Environment,TEE)來實現。TEE就是基
于TrustZone技術建立的具有更高安全級別的可信執(zhí)
行環(huán)境,運行在TEE環(huán)境下的應用稱為可信應用程
序(Trusted Application,TA)。隨著TEE可信應用
開發(fā)的API的普及,國內越來越多的手機廠商開始
集成TEE以及相關的可信應用。TEE環(huán)境的提供商
也越來越多,從先前國外的Trustonic TEE、高通
QSEE到現在國內的豆莢、華為、瓶缽等,可以說
TEE的技術開發(fā)門檻在降低,應用熱度在提高。在
眾多TEE產品方案中,有一個優(yōu)秀的開源方案逐漸
進入人們的視野,那就是OP-TEE。OP-TEE(Open
Platform Trusted Execution Environment)由ST-
Ericsson創(chuàng)建,由STMicroelectronics維護,2014年
ARM的開源社區(qū)Linaro將OP-TEE方案開源。截至
目前,OP-TEE一直是Linaro社區(qū)在維護的核心安全
項目之一。目前看來,進入TEE領域最好的方式就
是學習成熟的OP-TEE方案。作者便是在學習OP-
TEE的過程中完成了本書,旨在為后繼的入門者掃
除一些障礙。
本書組織結構
本書將采取由淺入深的方式介紹TrustZone技術
的原理、OP-TEE的整體架構及其主要功能模塊的
原理,同時介紹如何基于OP-TEE進行可信應用、客戶端應用(Client Application,CA)、安全驅動
等功能的開發(fā)。
本書主要分為四篇,總計25章,各篇的主要內
容分別如下。
·第一篇,基礎技術篇(第1章~第4章),包
含TrustZone技術的背景和實現原理、系統(tǒng)基本框架
以及OP-TEE環(huán)境的搭建。
·第二篇,系統(tǒng)集成篇(第5章~第9章),分
析OP-TEE在REE和TEE中各個組件的作用和聯(lián)系,對于有一定嵌入式以及LinuxAndroid開發(fā)經驗的讀
者,該篇實質上給將OP-TEE集成到基于
ARMv7ARMv8處理器的開發(fā)平臺打下基礎。
·第三篇,OP-TEE內核篇(第10章~第17
章),包含OP-TEE內核的中斷處理、線程管理和
通信等主要功能的實現原理,使讀者對TEE OS的
架構設計有進一步認識。
·第四篇,應用開發(fā)篇(第18章~第25章),介紹基于OP-TEE在加密、解密、安全存儲等方面
的實際應用,以及如何開發(fā)基于OP-TEE的可信應
用程序。如果對OP-TEE有一定了解的讀者希望通
過實踐開發(fā)來了解TEE的工作原理,可以直接從應用開發(fā)篇學習。
OP-TEE的代碼量遠沒有Linux內核大,但其涉
及的設計之復雜、模塊之豐富也不是本書能完全涵
蓋的。我們的初衷是希望通過本書對重要模塊的代
碼和流程進行分析,使讀者對OP-TEE的架構有整
體的認識,之后看到其他部分也能做到舉一反三。
本書的主要代碼均引用自GitHub上OP-TEE開
源項目的源代碼(鏈接:https:github.comOP-
TEEoptee_os),作者在翻譯了一些代碼英文注釋
的基礎上根據自己的理解對部分代碼補充了更多的
注釋。如果讀者對書中代碼的中文注釋有疑問,可
參考上述鏈接中的原始代碼和注釋。另外,OP-
TEE也有詳細的文檔資料(https:github.comOP-
TEEoptee_ostreemasterdocumentation),強烈建
議英文基礎好的讀者結合本書和官方文檔來學習。
如發(fā)現本書有紕漏和錯誤,或者需要改進之處,希
望讀者不吝指出。
本書特色
俗話說,基礎打不牢,學問攀不高。本書采取
自下而上的方式從硬件的角度介紹了TrustZone技
術,并結合源代碼逐步剖析了基于TrustZone技術的
OP-TEE實現。在技術深度上,本書從入門者的角度出發(fā)由淺入深,從最基礎的開發(fā)環(huán)境的搭建到最
終的OP-TEE OS的內部實現都進行了介紹;從內容
易讀性上來講,本書提供了基礎的示例代碼和各種
算法的使用示例,并給出了所有示例的源代碼鏈接
及操作的實驗步驟。相信讀者通過邊學習邊實踐的
方式閱讀完本書后,能夠掌握TrustZone技術的基礎
原理和使用OP-TEE進行實際的應用開發(fā)。
由于任何TEE方案的源代碼都屬于芯片廠商的
商業(yè)機密,外界無法一覽各TEE方案的實現原理,且TrustZone也是最近幾年才被正式商用的,所以網
上的資料較少。本書是作者基于多年的工作積累并
對實際工作過程中遇見的問題進行整理后形成的。
本書讀者對象
·手機、嵌入式系統(tǒng)和芯片開發(fā)者及技術支持
人員;
·手機和嵌入式系統(tǒng)安全與可信應用(支付系
統(tǒng)、多媒體及身份識別等)開發(fā)人員;
·相關專業(yè)安全技術研究者和大專院校學生;
·廣大關心安全技術的愛好者。致謝
從萌生寫本書的念頭到最終完成初稿共花了一
年零三個月,一路走來歷經波折,其間獲得了許多
朋友和老師的幫助,感恩這一切。感謝他們曾經的
陪伴和咖啡,讓我有勇氣將本書寫完。
感謝邱國政(Koshi)的指導以及他為本書擬
定的大綱,感謝他在寫作期間提供的耐心的釋疑解
惑,并在初稿完成后擠出寶貴的時間審閱全稿,提
出建設性的修改意見。
感謝段富剛師兄在寫作初期的建議、支持和鼓
勵,以及在后期審稿階段給出的修改意見,因您一
語,才使我嘗試將博文整理成書稿,使內容更加完
善和系統(tǒng)。
感謝樊鵬對本書稿件的審閱及結合自身在NXP
車載芯片上集成OP-TEE的實際工作經驗對本書提
供的寶貴建議。
感恩家人在寫作期間給予的理解和支持。感恩
沈雪亮和林先賢曾經的教導,感謝王佞姐平時的關
心,感謝黃誠、龔強強、徐貴友等好友在我撰寫本
書期間給予的無私幫助和真切鼓勵。感謝孟慶洋博士、黃冕博士、王子亮總監(jiān)、尉
魯飛師兄對本書內容的認可和推薦。感謝鄧仰東老
師和朱捷編輯在審稿期間給予的非常有益的建議和
指導,讓本書的內容更加豐富和嚴謹。
感謝張星茹在我考研時提供的幫助,感恩大學
那么一幫人,十年友誼一直未變。
感謝OP-TEE開源項目組的各位大牛,正是你
們的分享精神賦予了開發(fā)者涉足TrustZone這片神秘
領地和一探TEE具體實現原理的機會。
最后僅以此書紀念自己曾經的三十年,感恩生
命中遇見的每一個人、大學同學(于洋、郭成飛、吼哥、濤哥、胖胖、石頭、王健等一幫兄弟)、研
究生同學(劉峰、孫登高、夏軒、劉智、陳耀
闖),以及所有的朋友,是你們的出現讓我過去的
三十年不曾遺憾。第一篇 基礎技術篇
第1章 可信執(zhí)行環(huán)境
第2章 ARM的TrustZone技術
第3章 ARM可信固件
第4章 OP-TEE運行環(huán)境的搭建及編譯第1章 可信執(zhí)行環(huán)境
1.1 系統(tǒng)存在的安全問題
隨著移動通信和互聯(lián)網技術的飛速發(fā)展,智能
設備在各個領域扮演著越來越重要的角色。據統(tǒng)
計,在2017年,中國使用智能手機上網的用戶數已
達6億之多。此外,無人駕駛、物聯(lián)網、網絡電視
等也都與智能設備相關,或者本身就是智能設備,它們都會用到操作系統(tǒng)。然而由于一些黑客能夠破
解智能設備的root權限,進而盜取用戶數據或其他
關鍵信息,造成用戶數據的泄露或濫用。其次,如
果用戶的車載系統(tǒng)被黑客獲取控制權限,其人身安
全將無從保障。因此手機互聯(lián)網領域、電視領域、物聯(lián)網領域以及車載領域的安全越來越顯得重要。
再者,智能設備上各種應用不斷涌現,若開發(fā)
人員在開發(fā)這些應用時沒有針對安全進行加固保
護,則黑客可能會利用這些應用本身固有的安全漏
洞獲取智能設備操系統(tǒng)的root權限,輕松截獲用戶
的敏感數據。鑒于此,如何保障智能設備的安全變
得越來越重要。
那么,如何消除甚至杜絕這類威脅呢?除了提
高系統(tǒng)被破解的難度之外,最好還要在系統(tǒng)中提供一個相對可信賴的運行環(huán)境,使用戶的關鍵數據或
應用在這個相對可信賴的環(huán)境中使用和運行。這樣
一來,即便系統(tǒng)被攻破,入侵者也無法直接獲取用
戶的重要信息,用戶的信息安全也就實現了,這就
是可信執(zhí)行環(huán)境(Trusted Execution Environment,TEE)的主要作用和理念。1.2 TEE如何保護數據安全
為了給移動設備提供一個安全的運行環(huán)境,ARM從ARMv6的架構開始引入了TrustZone技術。
TrustZone技術將中央處理器(Central Processing
Unit,CPU)的工作狀態(tài)分為了正常世界狀態(tài)
(Normal World Status,NWS)和安全世界狀態(tài)
(Secure World Status,SWS)。支持TrustZone技
術的芯片提供了對外圍硬件資源的硬件級別的保護
和安全隔離。當CPU處于正常世界狀態(tài)時,任何應
用都無法訪問安全硬件設備,也無法訪問屬于安全
世界狀態(tài)下的內存、緩存(Cache)以及其他外圍
安全硬件設備。
TEE基于TrustZone技術提供可信運行環(huán)境,還
為開發(fā)人員提供了應用程序編程接口(Application
Programming Interface,API),以方便他們開發(fā)實
際應用程序。
在整個系統(tǒng)的軟件層面,一般的操作系統(tǒng)(如
Linux、Android、Windows等)以及應用運行在正
常世界狀態(tài)中,TEE運行在安全世界狀態(tài)中,正常
世界狀態(tài)內的開發(fā)資源相對于安全世界狀態(tài)較為豐
富,因此通常稱運行在正常世界狀態(tài)中的環(huán)境為豐
富執(zhí)行環(huán)境(Rich Execution Environment,REE),而可信任的操作系統(tǒng)以及上層的可信應用
(Trusted Application,TA)運行于安全世界狀
態(tài),運行在安全世界狀態(tài)中的系統(tǒng)就是前文提到的
TEE。
對CPU的工作狀態(tài)區(qū)分之后,處于正常世界狀
態(tài)中的Linux即使被root也無法訪問安全世界狀態(tài)中
的任何資源,包括操作安全設備、訪問安全內存數
據、獲取緩存數據等。這很像一個保險箱,不管保
險箱的外在環(huán)境是否安全,其內部的物件都有足夠
的安全性。這是因為CPU在訪問安全設備或者安全
內存地址空間時,芯片級別的安全擴展組件會去校
驗CPU發(fā)送的訪問請求的安全狀態(tài)讀寫信號位
(Non-secure bit,NS bit)是0還是1,以此來判定
當前CPU發(fā)送的資源訪問請求是安全請求還是非安
全請求。而處于非安全狀態(tài)的CPU將訪問指令發(fā)送
到系統(tǒng)總線上時,其訪問請求的安全狀態(tài)讀寫信號
位都會被強制設置成1,表示當前CPU的訪問請求
為非安全請求。而非安全請求試圖去訪問安全資源
時會被安全擴展組件認為是非法訪問的,于是就禁
止其訪問安全資源,因此該CPU訪問請求的返回結
果要么是訪問失敗,要么就是返回無效結果,這也
就實現了對系統(tǒng)資源硬件級別的安全隔離和保護。
在真實環(huán)境中,可以將用戶的敏感數據保存到
TEE中,并由可信應用(Trusted Application,TA)使用重要算法和處理邏輯來完成對數據的處理。當
需要使用用戶的敏感數據做身份驗證時,則通過在
REE側定義具體的請求編號(IDentity,ID)從TEE
側獲取驗證結果。驗證的整個過程中用戶的敏感數
據始終處于TEE中,REE側無法查看到任何TEE中
的數據。對于REE而言,TEE中的TA相當于一個黑
盒,只會接受有限且提前定義好的合法調用,而至
于這些合法調用到底是什么作用,會使用哪些數
據,做哪些操作在REE側是無法知曉的。如果在
REE側發(fā)送的調用請求是非法請求,TEE內的TA是
不會有任何的響應或是僅返回錯誤代碼,并不會暴
露任何數據給REE側。1.3 現有TEE解決方案
TEE是一套完整的安全解決方案,主要包含正
常世界狀態(tài)的客戶端應用(Client Application,CA)、安全世界狀態(tài)的可信應用,可信硬件驅動
(Secure Driver,SD)以及可信內核系統(tǒng)(Trusted
Execution Environment Operation System,TEE
OS),其系統(tǒng)配置、內部邏輯、安全設備和安全資
源的劃分是與CPU的集成電路(Integrated Circuit,IC)設計緊密掛鉤的,使用ARM架構設計的不同
CPU,TEE的配置完全不一樣。國內外針對不同領
域的CPU也具有不同的TEE解決方案。
國內外各種TEE解決方案一般都遵循
GP(Global Platform)規(guī)范進行開發(fā)并實現相同的
API。GP規(guī)范規(guī)定了TEE解決方案的架構以及供TA
開發(fā)使用的API原型,開發(fā)者可以使用這些規(guī)定的
API開發(fā)實際的TA并能使其正常運行于不同的TEE
解決方案中。1.3.1 智能手機領域的TEE
智能手機領域的芯片廠商眾多,國外有高通
(Qualcomm)、三星(Samsung)、LG,國內有
展訊、聯(lián)發(fā)科(MediaTek)、威盛電子(VIA)、華為海思(Hisilicon)等,目前手機廠商和芯片廠
商支持的TEE解決關系如圖1-1所示。圖1-1 TEE解決方案關系
各家TEE解決方案的內部操作系統(tǒng)的邏輯會不一樣,但都能提供GP規(guī)范規(guī)定的API,對于二級廠
商或TA開發(fā)人員來說接口都是統(tǒng)一的。這些TEE解
決方案在智能手機領域主要用于實現在線支付(如
微信支付、支付寶支付)、數字版權保護(DRM、Winevine Level 1、China DRM)、用戶數據安全保
護、安全存儲、指紋識別、虹膜識別、人臉識別等
其他安全需求。這樣可以降低用戶手機在被非法
root之后帶來的威脅。
Google規(guī)定在Android M之后所有的Android設
備在使用指紋數據時都需要用TEE來進行保護,否
則無法通過Google的CTS認證授權,另外Android也
建議使用硬件Keymaster和gatekeeper來強化系統(tǒng)安
全性。1.3.2 智能電視領域的TEE
當前的智能電視領域大多是使用Android系統(tǒng)
來實現的,為保護二級廠商的視頻源數據以及各廠
家用戶會員權益不被盜取,需要使用TEE來實現數
字版權保護、會員鑒權、用戶賬號信息保護等安全
功能,而TEE方案一般都是由電視芯片廠商提供
的,且所有的TEE源代碼都不對外公開,即使是二
級廠商也無法獲取到TEE的源代碼。在我國的智能
電視領域,智能電視芯片主要有兩家:星辰半導體
(Mstar)和華為海思,兩家廠商使用的TEE方案都
不一樣。
Mstar早期的TEE方案是在CPU的一個類似于單
片機的核上運行Nuttx系統(tǒng)作為TEE OS來實現TEE
方案的,但最新的Mstar芯片已經改用OP-TEE方案
來實現TEE解決方案。
華為海思的安全操作系統(tǒng)(Secure Operating
System,Secure OS)是按照GP規(guī)范自主研發(fā)的
TEE解決方案,其手機芯片和智能電視芯片都是使
用這個TEE方案。華為海思的TEE增加了權限校驗
功能(類似于白名單機制),即在使用華為海思的
TEE方案提供的API實現特定安全功能的TA時,需
要將調用該TA對應的CA接口的進程或者服務的相關信息提前注冊到TEE后方能正常使用,否則會導
致調用失敗。1.3.3 IoT領域及其他領域的TEE
物聯(lián)網(Internet of Thing,IoT)領域和車載
系統(tǒng)領域將會是未來TEE方案使用的另外一個重要
方向,大疆無人機已經使用TEE方案來保護無人機
用戶的私人數據、航拍數據以及關鍵的飛控算法。
ARM的M系列也開始支持TrustZone技術,如何針
對資源受限的IoT設備實現TEE也是未來TEE的重要
發(fā)展方向之一。
而在車載領域NXP芯片已經集成OP-TEE作為
TEE方案,MediaTek的車載芯片也已集成了
Trustonic的TEE方案,相信在車載系統(tǒng)領域TEE也
將漸漸普及。1.4 為什么選擇OP-TEE
本書主要是介紹OP-TEE的實現原理,OP-TEE
是由非營利的開源軟件工程公司Linaro開發(fā)的,從
git上可以獲取OP-TEE的所有源代碼,且OP-TEE支
持的芯片也越來越多,相信未來OP-TEE將有可能
是TEE領域的Linux,并得到更加廣泛的運用。
OP-TEE是按照GP規(guī)范開發(fā)的,支持QEMU、Hikey(Linaro推廣的96Board系列平臺之一,使用
Hisilicon處理器)以及其他通用的ARMv7ARMv8
平臺,開發(fā)環(huán)境搭建方便,便于開發(fā)者開發(fā)自有的
上層可信應用,且OP-TEE提供了完整的軟件開發(fā)
工具包(Software Development Kit,SDK),方便
編譯TA和CA。OP-TEE遵循GP規(guī)范,支持各種加
解密和電子簽名驗簽算法以便實現DRM、在線支
付、指紋和虹膜識別功能。OP-TEE也支持在芯片
中集成第三方的硬件加解密算法。除此之外,在
IoT和車載芯片領域也大都使用OP-TEE作為TEE解
決方案。
OP-TEE由Linaro組織負責維護,安全漏洞補丁
更新和代碼迭代速度較快,系統(tǒng)的健壯性也越來越
好,所以利用OP-TEE來研究TrustZone技術的實現
并開發(fā)TA和CA將會是一個很好的選擇。本書涉及的內核源代碼使用的是OP-TEE 2.4版
本,書中所有的示例都在最新版本中測試通過。第2章 ARM的TrustZone技術
2.1 TrustZone技術
為提高系統(tǒng)的安全性,ARM早在ARMv6架構
中就引入了TrustZone技術[1]
,且在ARMv7和
ARMv8中得到增強,TrustZone技術能提供芯片級
別對硬件資源的保護和隔離,當前在手機芯片領域
已被廣泛應用。
[1] TrustZone硬件需求文檔:lcu14-
500armtrustedfirmware-140919105449-
phpapp02.pdf;TrustZone白皮書:PRD29-GENC-
009492C_TrustZone_security_whitepaper.pdf。2.1.1 片上系統(tǒng)硬件框架
一個完整的片上系統(tǒng)(System on Chip,SoC)
由ARM核、系統(tǒng)總線、片上RAM、片上ROM以及
其他外圍設備組件構成。只有支持TrustZone技術的
ARM核配合安全擴展組件,才能為整個系統(tǒng)提供芯
片硬件級別的保護和隔離。如圖2-1所示是一個支
持TrustZone的SoC的硬件框圖。
支持TrustZone技術的ARM核在運行時將工作
狀態(tài)劃分為兩種:安全狀態(tài)和非安全狀態(tài)。當處理
器核處于安全狀態(tài)時只能運行TEE側的代碼,且具
有REE側地址空間的訪問權限。當處理器核處于非
安全狀態(tài)時只能運行REE側的代碼,且只能通過事
先定義好的客戶端接口來獲取TEE側中特定的數據
和調用特定的功能。
系統(tǒng)通過調用安全監(jiān)控模式調用(secure
monitor call,smc)指令實現ARM核的安全狀態(tài)與
非安全狀態(tài)之間的切換。而ARM核對系統(tǒng)資源的訪
問請求是否合法,則由SoC上的安全組件通過判定
ARM核發(fā)送到SoC系統(tǒng)總線上的訪問請求中的安全
狀態(tài)讀寫信號位(Non-secure bit,NS bit)來決
定。只有當ARM核處于安全狀態(tài)(NS bit=0)時發(fā)
送到系統(tǒng)總線上的讀寫操作才會被識別為安全讀寫操作,對應TEE側的數據資源才能被訪問。反之,當ARM核處于非安全狀態(tài)(NS bit=1)時,ARM核
發(fā)送到系統(tǒng)總線上的讀寫操作請求會被作為非安全
讀寫操作,安全組件會根據對資源的訪問權限配置
來決定是否響應該訪問請求。這也是TrustZone技術
能實現對系統(tǒng)資源硬件級別的保護和隔離的根本原
因。
圖2-1 SoC硬件框2.1.2 ARMv7架構的TrustZone技術
ARMv7架構中使用了TrustZone技術的系統(tǒng)軟
件層面的框圖如圖2-2所示。
圖2-2 ARMv7系統(tǒng)軟件框架
在ARMv7架構中CPU在運行時具有不同的特權
等級,分別是PL0(USR)、PL1(FIQIRQ、SYS、ABT、SVC、UND和MON)以及
PL2(Hyp),即ARMv7架構在原有七種模式之上
擴展出了Monitor模式和Hyp模式。Hyp模式是ARM
核用于實現虛擬化技術的一種模式。系統(tǒng)只有在
Monitor模式下才能實現安全狀態(tài)和非安全狀態(tài)的切
換。當系統(tǒng)在REE側或者TEE側運行時,系統(tǒng)執(zhí)行
smc(安全監(jiān)控模式調用)指令進入Monitor模式,通過判定系統(tǒng)SCR寄存器中對應的值來確定請求來
源(REETEE)以及發(fā)送目標(REETEE),相關
寄存器中的值只有當系統(tǒng)處于安全態(tài)時才可以更
改,關于安全狀態(tài)與非安全狀態(tài)之間的切換過程,在本書第10章中將進行詳細介紹。2.1.3 ARMv8架構的TrustZone技術
在ARMv8架構中改用執(zhí)行等級(Execution
Level,EL)EL0~EL3來定義ARM核的運行等級,其中EL0~EL2等級分為安全態(tài)和非安全態(tài)。
ARMv8架構與ARMv7架構中ARM核運行權限的對
應關系如圖2-3所示。
圖2-3 ARMv7v8運行權限對比
ARMv7和ARMv8架構下特權等級和工作模式
的對應關系分別如表2-1所示。
表2-1 ARMv7和ARMv8架構下各模式對應關系ARMv7架構中的PL0(USR)對應ARMv8架構
中的EL0,PL1(SVCABTIRQFIQUNDSYS)對
應ARMv8架構中的EL1,ARMv7架構中的Hyp模式
對應ARMv8架構中的EL2,而ARMv7架構中的
Mon(Monitor)則對應于ARMv8架構中的EL3。
ARMv8架構同樣也是使用安全監(jiān)控模式調用
指令使處理器進入EL3,在EL3中運行的代碼負責
處理器安全狀態(tài)和非安全狀態(tài)的切換,其中關于
TEE和REE切換的處理方式與ARMv7架構中Monitor
模式下的處理方式類似,本書第10章將結合實際代
碼進行詳細分析。2.2 ARM安全擴展組件
TrustZone技術之所以能提高系統(tǒng)的安全性,是
因為對外部資源和內存資源的硬件隔離。這些硬件
隔離包括中斷隔離、片上RAM和ROM的隔離、片
外RAM和ROM的隔離、外圍設備的硬件隔離、外
部RAM和ROM的隔離等。實現硬件層面的各種隔
離,需要對整個系統(tǒng)的硬件和處理器核做出相應的
擴展。這些擴展包括:
·對處理器核的虛擬化,也就是將AMR處理器
的運行狀態(tài)分為安全態(tài)和非安全態(tài)。
·對總線的擴展,增加安全位讀寫信號線。
·對內存管理單元(Memory Management
Unit,MMU)的擴展,增加頁表的安全位。
·對緩存(Cache)的擴展,增加安全位。
·對其他外圍組件進行了相應的擴展,提供安
全操作權限控制和安全操作信號。2.2.1 AXI總線上安全狀態(tài)位的擴展
為了支持TrustZone技術,控制處理器在不同狀
態(tài)下對硬件資源訪問的權限,ARM對先進可擴展接
口(Advanced eXtensible Interface,AXI)系統(tǒng)總線
進行了擴展。在原有AXI總線基礎上對每一個讀寫
信道增加了一個額外的控制信號位,用來表示當前
的讀寫操作是安全操作還是非安全操作,該信號位
稱為安全狀態(tài)位(NS bit)或者非安全狀態(tài)位
(Non-Secure bit)。
·AWPROT[1]:總線寫事務——低位表示安全
寫事務操作,高位表示非安全寫事務操作。
·ARPROT[1]:總線讀事務——低位表示安全
讀事務操作,高位表示非安全讀事務操作。
當主設備通過總線發(fā)起讀寫操作時,從設備或
者外圍資源同時也需要將對應的PROT控制信號發(fā)
送到總線上。總線或者從設備的解碼邏輯必須能夠
解析該PROT控制信號,以便保證安全設備在非安
全態(tài)下不被非法訪問。所有的非安全主設備必須將
安全狀態(tài)位置成高位,這樣就能夠保證非安全主設
備無法訪問到安全從設備。如果一個非安全主設備
試圖訪問一個安全從設備,將會在總線或者從設備上觸發(fā)一個錯誤操作,至于該錯誤如何處理就依賴
于從設備的處理邏輯和總線的配置。通常這種非法
操作最終將產生一個SLVERR(slave error)或者
DECERR(decode error)。2.2.2 AXI-to-APB橋的作用
TrustZone同樣能夠保護外圍設備的安全,例如
中斷控制、時鐘、IO設備,因此Trust-Zone架構還
能用來解決更加廣泛的安全問題。比如一個安全中
斷控制器和安全時鐘允許一個非中斷的安全任務來
監(jiān)控系統(tǒng),能夠為DRM提供可靠的時鐘,能夠為用
戶提供一個安全的輸入設備從而保證用戶密碼數據
不會被惡意軟件竊取。
AMBA3規(guī)范包含了一個低門數、低帶寬的外
設總線,被稱作外設總線(Advanced Peripheral
Bus,APB),APB通過AXI-to-APB橋連接到系統(tǒng)
總線上。而APB總線并不具有安全狀態(tài)位,為實現
APB外設與TrustZone技術相兼容,APB-to-AXI橋將
負責管理APB總線上設備的安全。APB-to-AXI橋會
拒絕不匹配的安全事務設置,并且不會將該事務請
求發(fā)送給外設。2.2.3 TrustZone地址空間控制組件
TrustZone地址空間控制組件(TrustZone
Address Space Controller,TZASC)[1]
是AXI總線上
的一個主設備,TZASC能夠將從設備全部的地址空
間分割成一系列的不同地址范圍。在安全狀態(tài)下,通過編程TZASC能夠將這一系列分割后的地址區(qū)域
設定成安全空間或者是非安全空間。被配置成安全
屬性的區(qū)域將會拒絕非安全的訪問請求。
使用TZASC主要是將一個AXI從設備分割成幾
個安全設備,例如off-Soc、DRAM等。ARM的動態(tài)
內存控制器(Dynamic Memory Controller,DMC)
并不支持安全和非安全分區(qū)的功能。如果將DMC接
到TZASC上,就能實現DRAM支持安全區(qū)域和非安
全區(qū)域訪問的功能。需要注意的是,TZASC組件只
支持存儲映射設備對安全和非安全區(qū)域的劃分與擴
展,但不支持對塊設備(如EMMC、NAND flash
等)的安全和非安全區(qū)域的劃分與擴展。圖2-4所
示為使用TZASC組件的例子。圖2-4 TZASC組件示意
[1] TZASC文檔:
DDI0431C_tzasc_tzc380_r0p1_trm.pdf。2.2.4 TrustZone內存適配器組件
TrustZone內存適配器組件(TrustZone Memory
Adapter,TZMA)[1]
允許對片上靜態(tài)內存(on-SoC
Static Memory)或者片上ROM進行安全區(qū)域和非安
全區(qū)域的劃分。TZMA支持最大2MB空間的片上靜
態(tài)RAM的劃分,可以將2MB空間劃分成兩個部
分,高地址部分為非安全區(qū)域,低地址部分為安全
區(qū)域,兩個區(qū)域必須按照4KB進行對齊。分區(qū)的具
體大小通過TZMA的輸入信號R0SIZE來控制,該信
號來自TZPC的輸出信號TZPCR0SIZE。即通過編程
TZPC可以動態(tài)地配置片上靜態(tài)RAM或者ROM的大
小。使用TZMA組件的鏈接框圖如圖2-5所示。
圖2-5 使用TZMA組件的鏈接示意
[1] TZMA文檔:
cycle_models_BP141_TZMA_User_Guide_v9_1_0_DUI1083A_en.pdf。2.2.5 TrustZone保護控制器組件
TrustZone保護控制器組件(TrustZone
Protection Controller,TZPC)[1]
是用來設定
TZPCDECPORT信號和TZPCR0SIZE等相關控制信
號的。這些信號用來告知APB-to-AXI對應的外設是
安全設備還是非安全設備,而TZPCR0SIZE信號用
來控制TZMA對片上RAM或片上ROM安全區(qū)域大
小的劃分。TZPC包含三組通用寄存器
TZPCDECPROT[2:0],每組通用寄存器可以產生8
種TZPCDECPROT信號,也就是TZPC最多可以將
24個外設設定成安全外設。TZPC組件還包含一個
TZPCROSIZE寄存器,該寄存器用來為TZMA提供
分區(qū)大小信息。TZPC組件的接口示意如圖2-6所
示。
當上電初始化時,TZPC的TZPCDECROT寄存
器中的位會被清零,同時TZPCR0SIZE寄存器會被
設置成0x200,表示接入到TZMA上的片上RAM或
者ROM的安全區(qū)域大小為2MB。通過修改TZPC的
寄存器配置的值可實現用戶對資源的特定配置。
TZPC的使用例子如圖2-7所示。圖2-6 TZPC組件接口示意
圖2-7 TZPC使用示例
[1] TZPC文檔(BP147):
DTO0015_primecell_infrastructure_amba3_tzpc_bp147_to.pdf。2.2.6 TrustZone中斷控制器組件
在支持TrustZone的SoC上,ARM添加了
TrustZone中斷控制器(TrustZone Interrupt
Controller,TZIC)[1]。TZIC的作用是讓處理器處
于非安全態(tài)時無法捕獲到安全中斷。TZIC是第一級
中斷控制器,所有的中斷源都需要接到TZIC上。
TZIC根據配置來判定產生的中斷類型,然后決定是
將該中斷信號先發(fā)送到非安全的向量中斷控制器
(Vector Interrupt Controller,VIC)后以nIRQ信號
發(fā)送到處理器,還是以nTZICFIQ信號直接發(fā)送到
處理器。圖2-8所示為TZIC在SoC中的使用示意。
圖2-8 TZIC在SoC中的使用示意
通過對TZIC的相關寄存器進行編程,可對
TZIC進行配置并設定每個接入到TZIC的中斷源的中斷類型。TZIC具有眾多寄存器,細節(jié)說明可以參
考相關ARM的文檔。在TZIC中用來設置中斷源類
型的寄存器為TZICIntSelect,如果TZICIntSelect中
的某一位被設置成1,則該相應的中斷源請求會被
設置成快速中斷請求(Fast Interrupt Request,FIQ)。如果某一位被設置成0,則該中斷源的中斷
請求會被交給VIC進行處理。如果VIC的IntSelect將
獲取到的中斷源設置成FIQ,那么該中斷源會被再
次反饋給TZIC進行處理。
[1] TZIC文檔:
DTO0013B_tzic_sp890_r0p0_to.pdf。2.2.7 Cache和MMU的擴展
在支持TrustZone的SoC上,會對MMU進行虛
擬化,使得寄存器TTBR0、TTBR1、TTBCR在安
全狀態(tài)和非安全狀態(tài)下是相互隔離的,因此兩種狀
態(tài)下的虛擬地址轉換表是獨立的。
存放在MMU中的每一條頁表描述符都會包含
一個安全狀態(tài)位,用以表示被映射的內存是屬于安
全內存還是非安全內存。虛擬化的MMU共享轉換
監(jiān)測緩沖區(qū)(Translation Lookaside Buffer,TLB),同樣TLB中的每一項也會打上安全狀態(tài)位
標記,只不過該標記是用來表示該條轉換是正常世
界狀態(tài)轉化的還是安全世界狀態(tài)轉化的。
Cache也同樣進行了擴展,Cache中的每一項都
會按照安全狀態(tài)和非安全狀態(tài)打上對應的標簽,在
不同的狀態(tài)下,處理器只能使用對應狀態(tài)下的
Cache。2.3 TrustZone技術對資源隔離的實現
ARM處理器核的虛擬化和資源隔離是
TrustZone實現安全需求的根本。支持TrustZone的
處理器核具有虛擬化,也即將一個物理核分成安全
狀態(tài)和非安全狀態(tài)。當處理器處于非安全狀態(tài)時,只能訪問屬于非安全的外設和內存,而不能訪問安
全的資源;當處理器處于安全態(tài)時,處理器既可以
訪問安全資源,也可以訪問非安全的資源,只有當
處理器核為安全世界狀態(tài)時才可能發(fā)出PROT的安
全訪問信號。2.3.1 中斷源的隔離
在原來的ARM芯片中,使用VIC來對外部中斷
源進行控制和管理,支持TrustZone后,ARM提出
了TZIC組件,在芯片設計時,該組件作為一級中斷
源控制器,控制所有的外部中斷源,通過編程TZIC
組件的相關寄存器來設定哪個中斷源為安全中斷源
FIQ,而未被設定的中斷源將會被傳遞給VIC進行
處理。一般情況下VIC會將接收到的中斷源設定成
普通中斷請求(Interrupt Request,IRQ),如果在
VIC中將接收到的中斷源設定成FIQ,則該中斷源
會被反饋給TZIC組件,TZIC組件會將安全中斷源
送到安全世界狀態(tài)中進行處理。2.3.2 片上RAM和片上ROM的隔離
芯片內部存在小容量的RAM或者ROM,以供
芯片上電時運行芯片ROM或者存放芯片自身相關的
數據。TrustZone架構對該部分也進行了隔離操作。
隔離操作通過使用TZMA和TZPC組件來實現。
TZMA用來將片上RAM或者ROM劃分成安全
區(qū)域和非安全區(qū)域,安全區(qū)域的大小則由接入的
TZPCR0SIZE信號來決定。而TZPCR0SIZE的值可
以通過編程TZPC組件中的TZPCR0SIZE寄存器來實
現。
當處理器核訪問片上RAM或者ROM時,TZMA會判定訪問請求的PROT信號是安全操作還
是非安全操作,如果處理器發(fā)出的請求為非安全請
求而該請求又嘗試去訪問安全區(qū)域時,TZMA就會
認為該請求為非法請求。這樣就能實現片上RAM和
ROM的隔離,達到非安全態(tài)的處理器核無法訪問片
上安全區(qū)域的RAM和ROM。2.3.3 片外DRAM的隔離
一個完整的系統(tǒng)必然會有片外RAM,對片外
RAM的隔離是通過TZASC組件實現的,ARM本身
的DMC可以將DRAM分割成不同的區(qū)域,這些區(qū)域
是沒有安全和非安全分類。將DMC與TZASC相連
后再掛到總線上,通過對TZASC組件進行編程可以
將DRAM劃分成安全區(qū)域和非安全區(qū)域。當主設備
訪問DRAM時,除需要提供物理地址之外,還會發(fā)
送PROT信號。TZASC組件首先會判定主設備需要
訪問的DARM地址是屬于安全區(qū)域還是非安全區(qū)
域,然后再結合接收到的PROT信號來判定該次訪
問是否有效。如果PROT信號為非安全訪問操作,且訪問的DRAM地址屬于安全區(qū)域,則TZASC就不
會響應這次訪問操作,這樣就能實現DRAM中安全
區(qū)域和非安全區(qū)域的隔離。2.3.4 外圍設備的隔離
其他外圍設備都會掛載到APB總線上,然后通
過AXI-to-APB橋連接到AXI總線上,AXI-to-APB結
合TZPC組件的TZPCDECROT的值及訪問請求的
PROT信號來判定該訪問是否有效。當處理器需要
訪問外圍設備時,會將地址和PROT信號發(fā)送到
AXI總線上。
AXI-to-APB橋會對接收到的請求進行解析,獲
取需要訪問的所需外圍設備,然后通過查詢
TZPCDECROT的值來判斷外設的安全類型,再根
據PROT信號就能判定該請求的安全類型。如果該
請求是非安全請求,但需要訪問的外圍設備屬于安
全設備,則AXI-to-APB會判定該訪問無效。
通過對TZPC中的TZPCDECROT寄存器進行編
程能夠設置外設的安全類型,從而做到外設在硬件
層面的隔離。2.4 小結
本章介紹了TrustZone的原理以及在ARMv7和
ARMv8架構下TrustZone技術實現的差異。
TrustZone對系統(tǒng)實現了硬件隔離,將系統(tǒng)資源劃分
成安全和非安全兩種類型,同時在系統(tǒng)總線上增加
安全讀寫信號位,通過讀取安全讀寫信號位電平來
確定當前處理器的工作狀態(tài),從而判斷是否具有該
資源的訪問權限。因此,TrustZone從硬件級別實現
了對系統(tǒng)資源的保護。第3章 ARM可信固件
3.1 為什么使用ATF
ARM可信任固件(ARM Trusted Firmware,ATF)是由ARM官方提供的底層固件,該固件統(tǒng)一
了ARM底層接口標準,如電源狀態(tài)控制接口
(Power Status Control Interface,PSCI)、安全啟
動需求(Trusted Board Boot Requirements,TBBR)、安全世界狀態(tài)(SWS)與正常世界狀態(tài)
(NWS)切換的安全監(jiān)控模式調用(secure monitor
call,smc)操作等。ATF旨在將ARM底層的操作統(tǒng)
一使代碼能夠重用和便于移植。3.2 ATF的主要功能
ATF的源代碼共分為bl1、bl2、bl31、bl32、bl33部分,其中bl1、bl2、bl31部分屬于固定的固
件,bl32和bl33分別用于加載TEE OS和REE側的鏡
像。整個加載過程可配置成安全啟動的方式,每一
個鏡像文件在被加載之前都會驗證鏡像文件的電子
簽名是否合法。
ATF主要完成的功能如下:
·初始化安全世界狀態(tài)運行環(huán)境、異常向量、控制寄存器、中斷控制器、配置平臺的中斷。
·初始化ARM通用中斷控制器(General
Interrupt Controller,GIC)2.0版本和3.0版本的驅動
初始化。
·執(zhí)行ARM系統(tǒng)IP的標準初始化操作以及安全
擴展組件的基本配置。
·安全監(jiān)控模式調用(Secure Monitor Call,smc)請求的邏輯處理代碼(Monitor模式EL3)。
·實現可信板級引導功能,對引導過程中加載的鏡像文件進行電子簽名檢查。
·支持自有固件的引導,開發(fā)者可根據具體需
求將自有固件添加到ATF的引導流程中。3.3 ATF與TEE的關系
為規(guī)范和簡化TrustZone OS的集成,在ARMv8
架構中,ARM引入ATF作為底層固件并開放了源
碼,用于完成系統(tǒng)中BootLoader、Linux內核、TEE
OS的加載和啟動以及正常世界狀態(tài)和安全世界狀態(tài)
的切換。ATF將整個啟動過程劃分成不同的啟動階
段,由BLx來表示。例如,TEE OS的加載是由ATF
中的bl32來完成的,安全世界狀態(tài)和正常世界狀態(tài)
之間的切換是由bl31來完成的。在加載完TEE OS之
后,TEE OS需要返回一個處理函數的接口結構體
變量給bl31。當在REE側觸發(fā)安全監(jiān)控模式調用指
令時,bl31通過查詢該結構體變量就可知需要將安
全監(jiān)控模式調用指令請求發(fā)送給TEE中的那個接口
并完成正常世界狀態(tài)到安全世界狀態(tài)的切換。3.4 小結
在ARMv8架構中,如果系統(tǒng)需要支持TEE,則
幾乎都必須使用由ARM提供的ATF作為底層固件。
關于ATF如何管理BootLoader、TEE OS、Linux內
核以及各個階段鏡像的加載過程和跳轉過程,本書
第6章將結合實際代碼詳細分析。第4章 OP-TEE運行環(huán)境的搭建及編
譯
OP-TEE是開源的TEE解決方案,任何人都可
從github庫中獲取OP-TEE的源代碼,本章主要包括
如何從github中獲取OP-TEE的源代碼、如何搭建運
行環(huán)境以及整個OP-TEE工程的編譯過程。本書以
QEMU作為運行平臺,Hikey或者其他平臺的編譯
和使用方式與QEMU平臺類似。4.1 獲取OP-TEE代碼并搭建運行環(huán)境
OP-TEE的開發(fā)環(huán)境推薦使用Linux進行搭建,可在Windows系統(tǒng)中使用虛擬機創(chuàng)建一個Ubuntu系
統(tǒng)或者將計算機系統(tǒng)換成Ubuntu系統(tǒng)。4.1.1 OP-TEE開發(fā)環(huán)境的搭建
OP-TEE的開發(fā)環(huán)境依賴于各種基本庫,在
Ubuntu系統(tǒng)中直接運行如下指令就可安裝OP-TEE
開發(fā)環(huán)境需要使用的各種依賴庫。
sudo apt-get install android-tools-adb android-tools-fastboot autoconf automake bc bison build-essential cscope curl device-tree-compiler expect flex ftp-upload gdisk iasl libattr1-dev libc6:i386 libcap-dev libfdt-dev libftdi-dev libglib2.0-dev libhidapi-dev libncurses5-dev libpixman-1-dev libssl-dev libstdc++6:i386 libtool libz1:i386 make mtools netcat python-crypto python-serial python-wand unzip uuid-dev xdg-utils xterm xz-utils zlib1g-dev4.1.2 獲取OP-TEE的源代碼
在系統(tǒng)中創(chuàng)建用于存放OP-TEE的目錄“open-
tee”,讀者可以根據自己的喜好替換目錄的名字,創(chuàng)建完目錄后就需要建立OP-TEE的repo(關于repo
或者git的使用,請讀者自行查找資料了解),初始
化完repo后,使用repo sync指令就可從Github上獲
取到OP-TEE的源代碼,操作如下:
mkdir open-tee 創(chuàng)建目錄
cd open-tee 切換到創(chuàng)建的目錄
repo init -u https: github.comOP-TEEmanifest.git -m default.xml --repo-url=git:codeaurora.orgtoolsrepo.git -b 2.6.0 初始化repo
repo sync 開始獲取OP-TEE源代碼
如果在執(zhí)行repo sync時出現“remote:
Repository not found”的報錯提示,則需要修改open-
tee.repo目錄下的manifest.xml文件,將該文件中所
有project域中的“.git”刪除,也可通過如下指令進行
修改:
sed -i s\.gitg .repomanifest.xml
修改完成之后,重新執(zhí)行repo sync來獲取OP-
TEE的代碼。manifest.xml文件中包含的就是整個工
程所需的單獨git倉庫的鏈接[1]。待代碼同步完成后,為方便后續(xù)章節(jié)中各示例
代碼的集成,需要使用如下指令將相關的代碼回滾
到標簽為3.0.0的版本。
cd optee_client
git checkout 3.0.0
cd optee_test
git checkout 3.0.0
cd optee_benchmark
git checkout 3.0.0
cd optee_examples
git checkout 3.0.0
cd optee_os
git checkout 3.0.0
[1] OP-TEE工程源代碼鏈接:https:github.comOP-
TEE;OP-TEE內核代碼鏈接:
https:github.comOP-TEEoptee_os;OP-TEE client
端代碼鏈接:https:github.comOP-
TEEoptee_client;OP-TEE test代碼鏈接:
https:github.comOP-TEEoptee_test;OP-TEE工程
使用的Linux Kernel代碼鏈接:
https:github.comlinaroswglinux;OP-TEE 中使用
的QEMU 軟件源代碼鏈接:
https:github.comlinaro-swgqemu。4.1.3 獲取編譯OP-TEE的toolchain
OP-TEE工程的源代碼下載完成后,下一步就
需要獲取編譯OP-TEE時使用的toolchain,切換到源
代碼的build目錄,執(zhí)行如下指令:
cd build 切換到build目錄
make -f toolchain.mk toolchains 下載toolchain
查看toolchain.mk文件可知,執(zhí)行make指令之
后,系統(tǒng)會去下載toolchains的tar包,包括32位和64
位的編譯鏈接工具,下載完成后會進行解壓操作。
執(zhí)行完make后,可發(fā)現OP-TEE源代碼的根目錄下
會多出一個toolchains的目錄,該目錄中存放的就是
編譯OP-TEE工程時使用的所有編譯鏈接工具。4.1.4 編譯QEMU
OP-TEE源代碼的build目錄是用于編譯整個工
程的編譯目錄,該目錄包含各種平臺的編譯配置文
件。在QEMU平臺運行時需選擇qemu.mk文件進行
編譯,具體操作如下:
cd build 切換到build目錄
make -f qemu.mk all 編譯工程
當然,讀者也可將qemu.mk文件鏈接成
Makefile,然后在build目錄下直接執(zhí)行make all就能
編譯QEMU平臺的工程。
編譯完成后將會在OP-TEE的根目錄下生成一
個out目錄,該目錄中存放的就是使用QEMU方式運
行OP-TEE時需要的鏡像和其他相關文件。
如果在編譯的過程中出現“ImportError:No
Module named wand.image”的報錯提示,說明系統(tǒng)
沒有安裝Python的Wand包,此時在shell中運行如下
指令即可:
pip install: Wand4.1.5 運行OP-TEE
工程編譯完成之后,如果要運行OP-TEE,則
需要進入build目錄中執(zhí)行make run-only語句,具體
操作如下:
cd build 切換到build目錄
make -f qemu.mk run-only 啟動QEMU并運行OP-TEE
如果讀者已將qemu.mk文件鏈接成了
Makefile,則直接在build目錄中執(zhí)行make run-only
即可。qemu.mk文件中的run-only目標首先會啟動兩
個分別屬于安全世界狀態(tài)和正常世界狀態(tài)的
terminal,用于顯示OP-TEE和Linux內核的日志數
據,然后加載OP-TEE鏡像與Linux的鏡像及其文件
系統(tǒng)。4.1.6 運行xtest和optee_example_hello_world
通過使用make run-only啟動OP-TEE后,可在
啟動的正常世界狀態(tài)對應的terminal中執(zhí)行
Optee_example_hello_world或者xtest指令來檢查OP-
TEE是否正常運行。
Optee_example_hello_world是一個簡單的CA編
譯而成的二進制可執(zhí)行文件,執(zhí)行該可執(zhí)行文件后
會調用OP-TEE中對應的TA,并執(zhí)行一些簡單的打
印操作,輸出的日志信息可在安全世界狀態(tài)的
terminal中查看。
xtest是OP-TEE自帶的一個測試使用的CA可執(zhí)
行文件。該CA執(zhí)行后將會調用TA中的各種功能,包括檢查基本算法接口、安全存儲接口等。4.2 運行CA和TA示例
OP-TEE中自帶的TA和CA都保存在
optee_examples目錄中,那么如何添加自己開發(fā)的
TA和CA程序到OP-TEE中并運行呢?本節(jié)將對此進
行介紹。為減少對編譯方面的理解,本節(jié)將結合實
際的TA和CA示例介紹詳細的操作步驟。4.2.1 示例代碼的獲取和集成
本節(jié)所用示例的所有源代碼可從gitHub上獲
取,讀者可使用如下指令獲取到源代碼,示例包中
有對應的補丁,讀者直接合入補丁就可將該示例集
成到OP-TEE中,該示例的gitHub鏈接如下:
git clone https:github.comshuaifengyunoptee_my_test.git
獲取到示例代碼之后,切換到如下build目錄
下,然后使用git apply命令合入補丁文件后就可將
該示例集成到OP-TEE,合入補丁的操作步驟如
下:
1)將示例代碼中的
optee_mytest_common_3.0.0.patch文件和
optee_mytest_qemu_3.0.0.patch文件復制到build目錄
中。
2)切換到build目錄,使用如下命令合入補
。
git apply optee_mytest_common_3.0.0.patch
git apply optee_mytest_qemu_3.0.0.patch將補丁合入之后就可使用make-f qemu.mk all編
譯整個工程,然后使用make-f qemu.mk run-only來
啟動OP-TEE,在啟動的正常世界狀態(tài)的終端執(zhí)行
my_test命令就能實現該示例的CA對TA的調用。示
例代碼的運行效果如圖4-1所示。
圖4-1 optee_my_test示例運行4.2.2 目錄和文件創(chuàng)建
從gitHub上獲取到本章使用的示例代碼后,host存放的是CA的代碼,ta目錄存放的是TA部分的
代碼。本章提供的示例代碼的目錄結構如下:
├── Android.mk
├── build_ta_mytest_qemu.sh
├── doc
│ ├── close_session_and_finalize_context.msc
│ ├── invoke_command.msc
│ ├── Makefile
│ └── open_session.msc
├── host
│ ├── main.c
│ ├── Makefile
│ └── my_test_ca.h
├── Makefile
├── optee_mytest_common_3.0.0.patch
├── optee_mytest_qemu_3.0.0.patch
├── README.md
└── ta
├── Android.mk
├── include
│ ├── my_test_handle.h
│ └── my_test_ta.h
├── Makefile
├── my_test.c
├── my_test_handle.c
├── sub.mk
└── user_ta_header_defines.h
目錄中文件的作用說明如下:·Android.mk文件:Android系統(tǒng)中編譯整個TA
和CA時使用;
·build_ta_mytest_qemu.sh文件:單獨編譯TA和
CA使用的腳本文件;
·hostmain.c文件:CA的源代碼;
·hostMakefile文件:編譯CA時使用的makefile
文件;
·hostmy_test_ca.h文件:UUID、command ID
的宏定義;
·taMakefile文件:編譯TA時使用的makefile文
件;
·tamy_test.c文件:主要是存放TA部分代碼的
入口處理函數,CA的command請求最終會被
TA_InvokeCommandEntryPoint函數處理;
·tamy_test_handle.c文件:存放相應CA的
command請求的功能函數;
·tasub.mk文件:定義該TA中需要被編譯的
source code;·tauser_ta_header_defines.h文件:定義UUID等
相關宏;
·taincludemy_test_handle.h文件:定義了該TA
需要使用的類型;
·taincludemy_test_ta.h文件:定義了UUID的宏
以及與CA對應的command ID宏;
·optee_mytest_common_3.0.0.patch文件:將該
TA和CA集成到OP-TEE時buildcommon.mk文件使
用的補丁文件;
·optee_mytest_qemu_3.0.0.patch文件:將該TA
和CA集成到OP-TEE時builldqemu.mk文件使用的補
丁文件。4.2.3 CA端代碼的修改
若讀者需添加新的功能,可按照GP規(guī)范調用
REE側的相關接口,編輯完CA端的代碼后就需要修
改host目錄下的Makefile文件,將需要編譯進CA的
文件添加到Makefile中,主要是修改hostMakefile文
件中的OBJS變量和BINARY變量,其中OBJS變量
存放的是需要編譯到CA的目標文件或者庫文件,BINARY是編譯完成后的可執(zhí)行文件的名字。注
意,在CA的頭文件中需要定義UUID和command ID
的宏,且定義的內容需要與TA中的UUID和
command ID一致,否則執(zhí)行CA后將會導致調用失
敗,關于UUID的值并沒有特殊的要求,只需按照
其格式定義一個唯一的字符串即可。4.2.4 TA端代碼的修改
ta目錄中存放的是該TA的源代碼、makefile文
件和頭文件,其中ta目錄中必須存在一個
user_ta_header.h文件,該文件在編譯TA鏡像或者是
整個工程時會被使用到。在該文件中會定義UUID
的宏、該TA運行的堆?臻g的大小以及版本信
息。在TA的頭文件中需要定義UUID的宏和
command ID,且必須與CA中定義的一樣,否則CA
端將無法調用該TA中對應的操作。修改taMakefile
文件,將該文件中BINARY變量的值修改成與CA中
相同的UUID值。
修改完成后運行build_ta_mytest_qemu.sh腳本
就能單獨編譯CA和TA,如果出現錯誤,則根據提
示進行修改,編譯成功后會在ta目錄中生成與UUID
值一樣的elf文件,在host目錄中將會生成與
hostMakefile文件中BINARY變量的值一樣的文
件。4.2.5 TA和CA在OP-TEE的集成
單獨編譯TA和CA成功后,就需要將該TA和
CA集成到OP-TEE的工程中去,需要修改OP-TEE源
代碼中build目錄下的qemu.mk文件和common.mk文
件。
在buildqemu.mk文件中增加該TA的目標和依
賴關系,以本示例為例,對buildqemu.mk文件的修
改如下。
1)增加optee_my_test的編譯目標內容:
optee_my_test
Optee_mytest: optee_mytest-common
Optee_mytest-clean: optee_mytest-clean-common
2)將optee_mytest目標和optee_mytest-clean-
common目標添加到all中:
all: bios-qemu qemu soc-term optee-examples optee_my_test
clean: bios-qemu-clean busybox-clean linux-clean optee-os-clean optee-client-clean qemu-clean soc-term-clean check-clean optee_my_test-clean optee-examples-clean在buildcommon.mk文件中需要增加編譯該TA
和CA的路徑變量等信息,添加的內容如下。
1)增加TA和CA的代碼路徑:
OPTEE_MYTEST_PATH ?= (ROOT)optee_my_test
2)增加TA和CA的common目標:
optee_my_test
OPTEE_MYTEST_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: optee_my_test-common
optee_my_test-common: optee-os optee-client
(MAKE) -C (OPTEE_MYTEST_PATH) (OPTEE_MYTEST_COMMON_FLAGS)
OPTEE_MYTEST_CLEAN_COMMON_FLAGS ?= TA_DEV_KIT_DIR=(OPTEE_OS_TA_DEV_KIT_DIR)
.PHONY: optee_my_test-clean-common
optee_my_test-clean-common:
(MAKE) -C (OPTEE_MYTEST_PATH) (OPTEE_MYTEST_CLEAN_COMMON_FLAGS) clean
3)將該TA和CA添加到filelist-tee-common目標
的依賴關系中:
filelist-tee-common: optee-client xtest optee-examples optee_my_test
4)添加clean操作的依賴關系:optee-os-clean-common: xtest-clean optee-examples-clean optee_my_test-clean
5)在filelist-tee-common中添加TA和CA鏡像需
要被打包到文件系統(tǒng)中的操作:
@echo optee_mytest >> (fl)
@if [ -e (OPTEE_MYTEST_PATH)hostmy_test ]; then echo file binmy_test (OPTEE_MYTEST_PATH)hostmy_test 755 0 0 >> (fl); echo file liboptee_armtz9269fadd-99d5-4afb-a1dc-ee3e9c61b04c.ta (OPTEE_MYTEST_PATH)ta9269fadd-99d5-4afb-a1dc-ee3e9c61b04c.ta 444 0 0 >> (fl); fi4.3 OP-TEE源代碼結構
OP-TEE的源代碼包含運行OP-TEE時需要的所
有軟件源代碼,OP-TEE工程編譯完成后,整個源
代碼的目錄結構如下:
├── basicAlg_use
├── bios_qemu_tz_arm
├── build
├── busybox
├── gen_rootfs
├── linux
├── optee_benchmark
├── optee_client
├── optee_examples
├── optee_my_test
├── optee_os
├── optee_test
├── out
├── qemu
├── secStor_test
├── soc_term
└── toolchains
OP-TEE各子目錄中的代碼功能說明如下。
(1)bios_qemu_tz_arm目錄
在QEMU平臺中運行tz_arm的BIOS代碼,啟動
的最初階段會被使用到,用來加載Linux內核鏡
像、OP-TEE OS鏡像、rootfs并啟動Linux內核和OP-TEE OS。
(2)build目錄
OP-TEE工程的編譯目錄,包含各種mk文件和
相關配置文件,其中common.mk文件是工程的通用
mk文件,不同的CPU架構有不同的mk與之相對
應,編譯工程時可使用make-f的方式指定編譯哪個
板級的OP-TEE。
(3)busybox目錄
busybox的源代碼,編譯生成制作rootfs所需要
的文件和目錄。
(4)gen_rootfs目錄
存放制作rootfs時使用的相關腳本和配置文
件。
(5)linux目錄
Linux內核代碼,在drivertee目錄下存放的是
OP-TEE在REE側的驅動,任何在Linux用戶空間調
用CA的接口都會經過OP-TEE的REE側驅動處理之
后再轉發(fā)到TEE側。(6)optee_benchmark目錄
OP-TEE運行的性能測試工具,只保存CA端的
代碼,TA部分的代碼保存在OP-TEE OS中,作為
靜態(tài)TA集成到OP-TEE OS中。
(7)optee_client目錄
包含CA程序調用的用戶空間的接口庫
(libteec)的源代碼。其中tee_supplicant目錄中的
代碼會被編譯成一個可執(zhí)行文件,該可執(zhí)行文件在
Linux啟動時作為守護進程常駐在系統(tǒng)中,該守護
進程的主要作用是響應和處理來自TEE側的RPC請
求,這些RPC請求包括:加載TA鏡像、對文件系統(tǒng)
的操作、對SQL的操作、對EMMC RPMB的操作、網絡通信的socket操作等。
(8)optee_examples目錄
示例代碼,目錄下包含OP-TEE提供的各種示
例的TA和CA的所有代碼,啟動后,在REE對應的
terminal中執(zhí)行optee_example_hello_world命令后,會調用optee_example_hello_world的TA的邏輯,TA
根據接收到的command ID在OP-TEE中執(zhí)行對應的
操作。
(9)optee_os目錄存放OP-TEE OS的源代碼和相關文檔,編譯完
成之后,該目錄將會生成OP-TEE的鏡像文件。
(10)optee_test目錄
opentee的測試程序xtest的源代碼,主要用來測
試OP-TEE中提供的各種算法的邏輯并提供其他測
試功能。
(11)out目錄
編譯結果的輸出目錄(該目錄編譯完成之后才
會生成)。
(12)qemu目錄
QEMU源代碼,如果編譯的是qemu.mk,編譯
時將會使用到該目錄。
(13)soc_term目錄
在使用QEMU運行OP-TEE時,gnome-terminal
命令會啟動終端,用于建立啟動的兩個terminal的
端口監(jiān)聽,方便OP-TEE OS的log和Linux的log分別
輸出到對應的terminal中。
(14)toolchains目錄編譯時需要使用的編譯工具鏈,在build目錄下
執(zhí)行make–f toolchai.mk toolchains后將會生成該目
錄。4.4 OP-TEE編譯
整個OP-TEE工程的編譯是一個龐大的過程,牽扯到目標的依賴關系,本節(jié)以qemu.mk板級為
例,分析使用QEMU方式運行OP-TEE時的全部編
譯過程和目標依賴關系。4.4.1 編譯目標的依賴關系
編譯OP-TEE工程時各主要目標的依賴關系如
下:
all
├── bios-qemu
│ ├── optee-os
│ │ └── optee-os-common
│ └── update_rootfs
│ └── update_rootfs-common
│ ├── busybox
│ │ └── busybox-common
│ │ └── linux
│ │ └── linux-common
│ │ └── linux-defconfig
│ └── filelist-tee
│ └── filelist-tee-common
│ ├── f1
│ │ └── filelist-tee.txt
│ ├── optee-client
│ │ ├── common
│ │ └── optee-client
│ └── xtest
│ │ ├── optee-client
│ │ └── xtest-common
│ │ └── optee-os
│ │ └──optee-os-common
│ └── optee-examples
│ └── build_socterm
│ └── helloworld-common
│ ├──optee-client
│ └──optee-os
├── benchmark-app
├── qemu
│ └── build_qemu
└── soc-term
│ └── build_socterm └── optee-examples
│ └── build_socterm
│ └── helloworld-common
│ ├──optee-client
│ └──optee-os
QEMU目標會切換到QEMU目錄,并獲取
QEMU的配置文件,然后執(zhí)行make命令來編譯
QEMU目標。
soc-term目標會編譯soc-term目錄,生成一個
soc-term的可執(zhí)行文件,用于啟動兩個terminal。
bios-qemu目標依賴于update_rootfs和optee-os,update_rootfs和optee-os編譯完成之后會調用
biosqemu-comm宏定義的指令,該宏會編譯
bios_qemu_tz_arm目錄,該目錄編譯完成之后,會
生成啟動時需要的bios鏡像。
optee-os-common目標將編譯optee_os目錄,該
目錄編譯完成后將會生成tee.bin及其他的lib庫文
件。
busybox目標將編譯linux目錄和busybox目錄,生成Linux內核鏡像文件和制作rootfs需要的相關文
件。
filelist-tee目標將生成tee功能相關的文件和需要被掛載到rootfs中的映射圖,然后與系統(tǒng)的其他文
件的掛載映射關系一起保存到filelist-final.txt文件
中,用于生成filesystem.cpio.gz文件。
update_rootfs-common目標依賴于busybox和
filelist-tee目標,上述兩個目標編譯完成之后,將會
切換到gen_rootfs目錄中,調用gen_init_cpio命令生
成在啟動時需要使用的filesystem.cpio.gz文件。
Optee_examples目標包含OP-TEE提供的各種
TA部分和CA部分,編譯完成之后,會生成對應的
TA鏡像文件和CA的可執(zhí)行文件。
optee-client目標將對optee_client目錄進行編
譯,生成一系列的庫文件和可執(zhí)行文件,庫文件提
供了OP-TEE在Linux端的接口,將被所有CA調用。
tee-supplicant目標將會編譯生成一個tee_supplicant
的可執(zhí)行文件,該可執(zhí)行文件提供了optee_os訪問
文件系統(tǒng)的RPC接口以及加載具體的TA鏡像的功
能。
xtest目標將會編譯optee_test目錄,生成在xtest
集合中會使用的TA鏡像文件和xtest可執(zhí)行文件。4.4.2 bios.bin鏡像的生成過程
bios.bin鏡像是啟動時會被使用到的主要鏡像文
件,在執(zhí)行make run-only指令使用QEMU方式啟動
OP-TEE時,會借助qemu-system-arm命令來啟動OP-
TEE和Linux kern,并掛載Linux的rootfs。在運行
qemu-system-arm命令時,其中有一個參數為“-
bios”,該參數就是告訴QEMU使用該參數之后所帶
的bios.bin來啟動整個系統(tǒng)。
bios.bin中會包含Linux kernel的鏡像、OP-TEE
OS的鏡像以及rootfs。該鏡像文件是在bios-qemu的
目標中編譯出來的。
當bios-qemu目標的依賴目標都編譯完成后,會
使用bios-qemu-common函數將Linux內核、OP-TEE
鏡像、rootfs打包成bios.bin鏡像文件。bios-qemu-
common函數定義在buildqemu.mk文件中,內容如
下:
define bios-qemu-common
+(MAKE) -C (BIOS_QEMU_PATH) CROSS_COMPILE=(CROSS_COMPILE_NS_USER) O=(ROOT)outbios-qemu BIOS_NSEC_BLOB=(LINUX_PATH)archarmbootzImage BIOS_NSEC_ROOTFS=(GEN_ROOTFS_PATH)filesystem.cpio.gz BIOS_SECURE_BLOB=(OPTEE_OS_BIN) PLATFORM_FLAVOR=virtEndef
執(zhí)行該函數時會帶入相關的編譯參數,編譯由
變量BIOS_QEMU_PATH定義的目錄
(bios_qemu_tz_arm目錄),參數說明如下:
·CROSS_COMPILE:編譯時使用的編譯參
數,包括編譯器、cflag等;
·O:編譯結果的輸出目錄;
·BIO_NSEC_BLOB:定義該變量,指定Linux
內核鏡像的名稱和路徑;
·BIOS_NSEC_ROOTFS:定義該變量,指定生
成的rootfs存在的目錄和cpio格式文件名;
·BIOS_SECURE_BLOB:定義該變量,指定
OP-TEE OS鏡像文件名;
·PLATFORM_FLAVOR:定義該變量,設定平
臺變量。
編譯bios_qemu_tz_arm目錄時最終會將Linux內
核鏡像、OP-TEE OS鏡像、rootfs轉換成.o文件,然
后再將這些轉換后的.o文件與其他的.o文件一起鏈
接成biso.bin鏡像文件。Linux內核鏡像文件會被放在bios.bin中名稱為nsec_blob的section里。OP-TEE
os image將會被放在bios.bin中名稱為secure_blob的
section里。rootfs image將會被放在bios.bin中名稱為
nsec_rootfs的section里。
上述將鏡像文件轉換成.o文件的操作是通過
OBJCOPY帶--rename-section參數來實現的,具體的
內容可以在link.mk文件中找到。
bios_qemu_tz_armbiosentry.s文件存放的就是
在啟動系統(tǒng)時bios.bin的入口文件。4.4.3 run-only目標的執(zhí)行
qemu.mk文件中的run-only目標是用來啟動使用
QEMU方式運行OP-TEE的起始目標,在qemu.mk文
件中,run-only目標的定義如下:
.PHONY: run-only
run-only:
(call check-terminal)
(call run-help)
(call launch-terminal, 54320,Normal World)
(call launch-terminal, 54321,Secure World)
(call wait-for-ports, 54320,54321)
(QEMU_PATH)arm-softmmuqemu-system-arm -nographic -serial tcp:localhost:54320 -serial tcp:localhost:54321 -s -S -machine virt -machine secure=on -cpu ARM核-a15 -m 1057 -bios (ROOT)outbios-qemubios.bin (QEMU_EXTRA_ARGS)
run-only目標的內容會調用各種函數,這些函
數會在相關的makefile文件中定義,下面是相關函
數的作用說明:
(call check-terminal):
check-terminal在QEMU的工程中不會被定義,該語句不會被執(zhí)行,但是在其他工程中會定義,具
體可查看buildcommon.mk文件。(call run-help):
run-help函數定義在buildcommom.mk文件中,主要用來打印出相關的啟動幫助信息。
(call launch-terminal,54320,Normal
World):
執(zhí)行l(wèi)aunch-terminal,54320,Normal
World指令,啟動名字為Normal World的terminal,其中l(wèi)aunch-terminal在buildcommon.mk文件中定
義。
(call launch-terminal,54321,Secure
World):
執(zhí)行功能同上,只是在重定向時將端口換成了
54321,且啟動的terminal名字為Secure World。
(call wait-for-ports,54320,54321):
調用wait-for-prots函數,該函數定義在
buildcommon.mk文件中,主要功能是檢查上面啟
動的兩個terminal使用socket方式進行通信是否正
常。
(QEMU_PATH)arm-softmmuqemu-system-arm:
該指令就是調用qemu-system-arm指令,并設定
好QEMU啟動的各種參數,然后開始啟動Linux與
OP-TEE,該指令完全展開之后的內容如下:
homeicyshuaidevelopteebuild..qemuarm-softmmuqemu-system-arm -nographic -serial tcp:localhost:54320 -serial tcp:localhost:54321 -s -S -machine virt -machine secure=on -cpu ARM核-a15 -m 1057 -bios homeicyshuaidevelopteebuild..outbios-qemubios.bin
-nographic:不顯示圖形界面。
-serial:將串口重定向到后面的參數部分。
-S:使用C來控制啟動(在QEMU的console界
面輸入C之后才會正式啟動系統(tǒng))。
-m:設定虛擬的內存大小。
-bios:指定BIOS的文件(該image中會包含
OP-TEE、Linux、rootfs的鏡像文件)。
1.launch-terminal函數
launch-terminal函數的主要功能是用來啟動terminal。該函數定義在buildcommon.mk文件中,具體內容如下:
define launch-terminal
@nc -z 127.0.0.1 (1) || (gnome-terminal) -t (2) -x (SOC_TERM_PATH)soc_term (1)
endef
(gnome-terminal)的定義也在common.mk文件
中,定義如下:
gnome-terminal := (shell command -v gnome-terminal 2>devnull)
調用(call launch-terminal,54320,Normal
World)等價于:
gnome-terminal -t Normal World -x (SOC_TERM_PATH)soc_term 54320
調用該函數的作用是啟動一個名字為Normal
World的terminal,并且在terminal中執(zhí)行soc_term
54320,soc_term就是在soc_term目錄中編譯出來的
可執(zhí)行文件。執(zhí)行soc_term 54320命令的主要作用
是將該terminal的輸入和輸出通過54320端口重定向
到標準輸入和輸出端口。
2.soc_term可執(zhí)行文件soc_term可執(zhí)行文件用來實現Linux和OP-TEE
的兩個terminal輸入和輸出重定向到標準輸入輸出
端口,該可執(zhí)行文件的源代碼存放在soc_term目錄
中。soc_term.c文件中的main函數定義如下:
int main(int argc, char argv[])
{
int listen_fd;
char port;
bool have_handle_telnet_option = false;
switch (argc) {
case 2:
port = argv[1];
break;
case 3:
if (strcmp(argv[1], -t) != 0)
usage;
have_handle_telnet_option = true;
port = argv[2];
break;
default:
usage;
}
save_current_termios;獲取當前terminal的信息(標準輸入輸出的terminal配置)
listen_fd = get_listen_fd(port);建立socket機制,并監(jiān)聽輸入的端口號
printf(listening on port %s\n, port);
if (have_handle_telnet_option) 判定是否使用telent
printf(Handling telnet commands\n);
進入loop循環(huán),完成端口監(jiān)聽和輸入輸出的重定向
while (true) {
int fd = accept_fd(listen_fd); 開始接收建立的監(jiān)聽端口的信息
handle_telnet = have_handle_telnet_option;
handle_telnet_codes(-1,NULL, NULL); 為使用telent時不起作用
warnx(accepted fd %d, fd);
復制當前terminal的信息,并配置其他參數,然后調用tcsetattr函數來設定當前啟動的terminal的信息
set_tty_noncanonical;
開始處理監(jiān)聽收到的數據,并根據對應的revent進行重定向操作,server_fd函數的注釋見后續(xù)章節(jié)
serve_fd(fd);
處理完成之后關閉該fd
if (close(fd)) err(1, close);
fd = -1;
保存當前terminos的配置
restore_termios;
}
}
server_fd函數用來接收受監(jiān)控的端口的數據,并執(zhí)行重定向操作,代碼內容和解釋如下:
static void serve_fd(int fd)
{
uint8_t buf[512];
struct pollfd pfds[2];
設定pollfd參數,用于實現重定向操作
memset(pfds, 0, sizeof(pfds));
pfds[0].fd = STDIN_FILENO;
pfds[0].events = POLLIN;
pfds[1].fd = fd;
pfds[1].events = POLLIN;
while (true) {
size_t n;
獲取監(jiān)聽事件的pfds[0]和pfds[1]中定義的事件
if (poll(pfds, 2, -1) == -1)
err(1, poll);
如果pfds[0]中的POLLIN時間觸發(fā)(在該terminal的標準輸入中有輸入操作),則進行讀取操作
if (pfds[0].revents POLLIN) {
從該terminal的標準輸入端口中讀取輸入的數據
n = read(STDIN_FILENO, buf, sizeof(buf));
if (n == -1)
err(1, read stdin);
if (n == 0)
errx(1, read stdin EOF);
將讀取到的數據寫入到重定向的port捆綁的socket
if (!write_buf(fd, buf, n)) {
warn(write_buf fd);
break;
}
}
如果pfds[1]中的POLLIN時間觸發(fā)(監(jiān)測到該terminal的port捆綁的socket有輸入流操作),則讀取監(jiān)測的port對應的socket句柄中的數據 if (pfds[1].revents POLLIN) {
讀取與port捆綁的socket的句柄中的數據
n = read(fd, buf, sizeof(buf));
if (n == -1) {
warn(read fd);
break;
}
if (n == 0) {
warnx(read fd EOF);
break;
}
handle_telnet_codes(fd, buf, n);
將讀取到的數據寫入到該terminal的標準輸出
if (!write_buf(STDOUT_FILENO, buf, n))
err(1, write_buf stdout);
}
}
}4.5 小結
本章主要介紹OP-TEE開發(fā)和運行環(huán)境的搭
建,并提供了一個demo,介紹如何開發(fā)自己的TA
和CA并讓其成功運行在OP-TEE中。為方便讀者理
解整個OP-TEE工程的實際執(zhí)行流程,知道如何生
成啟動OP-TEE時使用的各種鏡像文件,本章特意
介紹了OP-TEE工程的編譯過程以及編譯過程中各
種目標的依賴關系,同時對編譯過程中的重要函數
做了進一步的介紹。第二篇 系統(tǒng)集成篇
第5章 QEMU運行OP-TEE的啟動過程
第6章 安全引導功能及ATF的啟動過程
第7章 OP-TEE OS的啟動過程
第8章 OP-TEE在REE側的上層軟件
第9章 REE側OP-TEE的驅動第5章 QEMU運行OP-TEE的啟動過
程
使用QEMU的方式運行OP-TEE是通過在build
目錄下執(zhí)行make run-only來啟動的,啟動過程主要
是加載bios.bin文件,并從該鏡像文件中分離出
Linux內核鏡像和OP-TEE鏡像以及rootfs鏡像,并將
rootfs作為根文件系統(tǒng)掛到Linux系統(tǒng)中。本章將介
紹系統(tǒng)的啟動過程,并詳細介紹OP-TEE的啟動流
程和相關的重要啟動節(jié)點。5.1 bios.bin的入口函數
使用QEMU運行OP-TEE時首先加載的是編譯
生成的bios.bin鏡像文件,而bios.bin鏡像文件的入
口函數是在bios_qemu_tz_armbiosentry.S文件中定
義的,該文件的入口函數為_start,該文件的主要內
容如下:
.section .text.boot
定義 _start函數,設定第一條指令跳轉到reset函數執(zhí)行
FUNC _start , :
b reset
b . Undef
b . Syscall
b . Prefetch abort
b . Data abort
b . Reserved
b . IRQ
b . FIQ
END_FUNC _start
reset 函數
LOCAL_FUNC reset , :
read_sctlr r0
orr r0, r0, SCTLR_A
write_sctlr r0
設置中斷向量表
adr r0, _start
write_vbar r0
重新設定bios在RAM中的地址
mov r0, 0
ldr r1, =__text_start
ldr r2, =__data_end
sub r2, r2, r1
復制bios.bin文件中的__text_start到__data_end到地址為0的起始RAM中
bl copy_blob
跳轉到上面重新定位的bios在RAM中的地址 ldr ip, =new_loc
bx ip
new_loc:
重新設定中斷向量
adr r0, _start
write_vbar r0
清空BSS段的數據
ldr r0, =__bss_start
ldr r1, =__bss_end
sub r1, r1, r0
bl zero_mem
設定堆?臻g
ldr ip, =main_stack_top;
ldr sp, [ip]
push {r0, r1, r2}
mov r0, sp
ldr ip, =main_init_sec 獲取main_init_sec函數地址
blx ip 跳轉到main_init_sec函數中執(zhí)行,加載OP-TEE OS的image
pop {r0, r1, r2}
mov ip, r0 OP-TEE OS的入口地址
mov r0, r1 argument (address of pagable part if != 0)
blx ip 跳轉到OP-TEE OS的啟動地址
設置Normal World的棧
ldr ip, =main_stack_top;
ldr sp, [ip]
ldr ip, =main_init_ns 獲取main_init_ns函數的地址
bx ip 跳轉到main_init_ns函數,加載Linux內核的image
END_FUNC reset
復制函數
LOCAL_FUNC copy_blob , :
ldrb r4, [r0], 1
strb r4, [r1], 1
subs r2, r2, 1
bne copy_blob
bx lr
END_FUNC copy_blob
清空內存數據的函數
LOCAL_FUNC zero_mem , :
cmp r1, 0
bxeq lr
mov r4, 0
strb r4, [r0], 1
sub r1, r1, 1
b zero_mem
END_FUNC zero_memmain_init_sec函數用來將Linux內核鏡像、OP-
TEE OS鏡像、rootfs鏡像文件加載到RAM的對應位
置,并且解析出OP-TEE OS的入口地址、Linux內
核的加載地址、rootfs在RAM中的地址和其他相關
信息。main_init_sec函數執(zhí)行完成后會返回OP-TEE
OS的入口地址以及設備樹(device tree,DT)的地
址,然后在匯編代碼中通過調用blx指令進入OP-
TEE OS的啟動。
OP-TEE啟動完成后會重新進入entry.S文件中
繼續(xù)執(zhí)行,最終執(zhí)行main_init_ns函數來啟動Linux
內核,在main_init_sec函數中會設定Linux內核的入
口函數地址、DT的相關信息,main_init_ns函數會
使用這些信息來開始Linux內核的加載。
上述兩個函數都定義在
bios_qemu_tz_armbiosmain.c文件中。將各種鏡像
文件復制到RAM的操作都是通過解析bios.bin鏡像
的對應section來實現的,通過尋找特定的section來
確定各鏡像文件在bios.bin文件中的位置。5.2 OP-TEE鏡像的加載和啟動
啟動過程中entry.S文件通過匯編調用
main_init_sec函數將optee-os鏡像、Linux鏡像和
rootfs加載到RAM中,并定位DT的地址信息,以備
Linux和OP-TEE啟動使用,這些操作是由
main_init_sec函數進行的,該函數定義在
bios_qemu_tz_armbiosmain.c文件中,其內容如
下:
void main_init_sec(struct sec_entry_arg arg)
{
void fdt;
int r;
定義OP-TEE OS 鏡像文件存放的起始地址
const uint8_t sblob_start = __linker_secure_blob_start;
定義OP-TEE OS 鏡像文件存放的末端地址
const uint8_t sblob_end = __linker_secure_blob_end;
struct optee_header hdr; 存放OP-TEE OS image頭的信息
size_t pg_part_size; OP-TEE OS image除去初始化頭部信息的大小
uint32_t pg_part_dst; OP-TEE OS image除去初始化頭部信息后在RAM中的起始地址
msg_init; 初始化uart
加載device tree 信息。在qemu工程中,并沒有將device tree信息編譯到Bios.bin中,而默認存放在DTB_START地址中
fdt = open_fdt(DTB_START, __linker_nsec_dtb_start,__linker_nsec_dtb_end);
r = fdt_pack(fdt);
CHECK(r < 0);
判定OP-TEE OS image的大小是否大于image header的大小
CHECK(((intptr_t)sblob_end - (intptr_t)sblob_start) <
(ssize_t)sizeof(hdr));
將OP-TEE OS image header信息復制到hdr變量中
copy_bios_image(secure header, (uint32_t)hdr, sblob_start,sblob_start + sizeof(hdr));
校驗OP-TEE OS image header中的magic和版本信息是否合法
CHECK(hdr.magic != OPTEE_MAGIC || hdr.version != OPTEE_VERSION); msg(found secure header\n);
sblob_start += sizeof(hdr); 將sblob_start的值后移到除去image header的位置
CHECK(hdr.init_load_addr_hi != 0); 檢查OP-TEE OS的初始化加載地址是否為零
獲取OP-TEE OS除去 image header和ini操作部分代碼后的大小
pg_part_size = sblob_end - sblob_start - hdr.init_size;
確定存放OP-TEE OS除去image header和init操作部分代碼后存放在RAM中的地址
pg_part_dst = (size_t)TZ_RES_MEM_START + TZ_RES_MEM_SIZE - pg_part_size;
將存放OP-TEE OS除去image header和init操作部分后的內容復制到RAM中
copy_bios_image(secure paged part,pg_part_dst, sblob_start + hdr.init_size, sblob_end);
sblob_end -= pg_part_size; 重新計算sblo_end的地址,剔除page part
將pg_part_dst賦值給arg中的paged_part以備跳轉執(zhí)行OP-TEE OS使用
arg->paged_part = pg_part_dst;
將hdr.init_load_addr_lo賦值給arg中的entry,該地址為op-TEE OS的入口地址
arg->entry = hdr.init_load_addr_lo;
將OP-TEE OS的實際image復制到起始地址為hdr.init_load_addr_l的RAM地址中
copy_bios_image(secure blob, hdr.init_load_addr_lo, sblob_start,sblob_end);
復制kernel image、rootfs到RAM,并復制device tree到對應地址,以備被kernel使用
copy_ns_images;
將device tree的地址賦值給arg->fdt變量,以備OP-TEE OS啟動使用
arg->fdt = dtb_addr;
msg(Initializing secure world\n);
}
main_init_sec函數執(zhí)行后將會返回一個
sec_entry_arg的變量,該變量包含啟動OP-TEE OS
的入口地址、DT的地址以及paged_table的地址。
sec_entry_arg變量將會被entry.S文件用來啟動OP-
TEE OS,entry.S會將OP-TEE OS的入口地址保存在
r0寄存器中,而paged_table部分的起始地址會被保
存在r1寄存器中,將r0賦值給ip,最終entry.S文件
通過執(zhí)行blx ip指令進入OP-TEE OS的入口函數中去
執(zhí)行OP-TEE OS的啟動。當OP-TEE OS啟動完成之
后,entry.S文件會調用main_init_ns函數來啟動Linux內核。待Linux內核啟動完成之后,整個系統(tǒng)
也就啟動完成。5.3 Linux內核鏡像的加載和啟動
entry.S文件通過調用main_init_ns函數來完成對
Linux內核的啟動,該函數會調用call_kernel函數來
完成Linux內核的啟動,調用call_kernel函數時傳入
的參數說明如下:
kernel_entry:Linux內核在RAM中的入口地
址,該值在main_init_sec函數中通過調用
copy_ns_images函數來進行賦值。
dtb_addr:DT存放的位置,該值在
main_init_sec函數中通過調用copy_ns_images函數來
進行賦值。
rootfs_start:復制到RAM中的rootfs的起始地
址,該值在main_init_sec函數中被賦值。
rootfs_end:復制到RAM中的rootfs的末端地
址,該值在main_init_sec函數中被賦值。
call_kernel函數定義在
bios_qemu_tz_armbiosmain.c文件中,該函數的內
容和相關注釋如下:typedef void (kernel_ep_func)(uint32_t a0, uint32_t a1, uint32_t a2);
static void call_kernel(uint32_t entry, uint32_t dtb,uint32_t initrd, uint32_t initrd_end)
{
定義指向Linux內核入口地址的函數指針,并將函數指針的地址指向帶入參數entry的位置
kernel_ep_func ep = (kernel_ep_func)entry;
void fdt = (void )dtb; 定義device tree的地址并賦值
const char cmdline[] = COMMAND_LINE; 定義存放command line的變量并進行賦值
int r;
const uint32_t a0 = 0;
MACH_VEXPRESS see linuxarcharmtoolsmach-types
const uint32_t a1 = 2272;
獲取device tree的信息
r = fdt_open_into(fdt, fdt, DTB_MAX_SIZE);
CHECK(r < 0);
設置device tree中的相關節(jié)點、initrd的起始地址、initrd的末端地址、bootargs
setprop_cell(fdt, chosen, linux,initrd-start, initrd);
setprop_cell(fdt, chosen, linux,initrd-end, initrd_end);
setprop_string(fdt, chosen, bootargs, cmdline);
r = fdt_pack(fdt);
CHECK(r < 0);
打印相關信息
msg(kernel command line: \%s\\n, cmdline);
msg(Entering kernel at 0x%x with r0=0x%x r1=0x%x r2=0x%x\n,(uintptr_t)ep, a0, a1, dtb);
帶入device tree信息和其他相關參數,調用Linux內核的入口函數,進而執(zhí)行Linux內核的啟動
ep(a0, a1, dtb);
}
ep的值是Linux內核的入口函數指針,所以最
終調用ep(a0,a1,dtb)函數就能開始Linux內核的啟
動過程。5.4 rootfs的掛載
啟動Linux系統(tǒng)時會加載rootfs,rootfs在啟動
Linux系統(tǒng)之前會被拷貝到相應的內存地址中,系
統(tǒng)在啟動Linux時會告知Linux內核rootfs在內存中的
地址,Linux內核啟動時會到該地址中去獲取rootfs
的內容,掛載起來作為Linux系統(tǒng)的根文件系統(tǒng)使
用。5.5 OP-TEE驅動的啟動
在OP-TEE工程中,OP-TEE在REE側的驅動會
被編譯到Linux內核鏡像中,Linux系統(tǒng)在啟動的過
程中會自動掛載OP-TEE的驅動,驅動掛載過程中
會創(chuàng)建devtee0和devteepriv0設備,其中devtee0
設備將會被REE側的用戶空間的庫(libteec)使
用,devteepriv0設備將會被系統(tǒng)中的常駐進程
tee_supplicant使用,并且在OP-TEE驅動的掛載過程
中會建立正常世界狀態(tài)與安全世界狀態(tài)之間的共享
內存,用于OP-TEE驅動與OP-TEE之間的數據共
享,同時還會創(chuàng)建兩個鏈表,分別用于保存來自
OP-TEE的RPC請求和發(fā)送RPC請求的處理結果給
OP-TEE。5.6 tee_supplicant的啟動
tee_supplicant是Linux系統(tǒng)中的常駐進程,該進
程用于接收和處理來自OP-TEE的RPC請求,并將
處理結果返回給OP-TEE。來自OP-TEE的RPC請求
主要包括socket操作、REE側文件系統(tǒng)操作、加載
TA鏡像文件、數據庫操作、共享內存分配和注冊
操作等。該進程在Linux系統(tǒng)啟動過程中被自動創(chuàng)
建,在編譯時,該進程的啟動信息會被寫入
到etcinit.d文件中,而該進程的可執(zhí)行文件則被保
存在文件系統(tǒng)的bin目錄下。該進程中會使用一個
loop循環(huán)接收來自OP-TEE的遠程過程調用
(Remote Procedure Call,RPC)請求,且每次獲取
到來自OP-TEE的RPC請求后都會自動創(chuàng)建一個線
程,用于接收OP-TEE驅動隊列中來自OP-TEE的
RPC請求,之所以這么做是因為時刻需要保證在
REE側有一個線程來接收OP-TEE的請求,實現RPC
請求的并發(fā)處理。5.7 小結
本章介紹了使用QEMU的方式運行OP-TEE的
啟動過程,介紹了系統(tǒng)是如何啟動的,在啟動過程
中如何加載相應的鏡像文件。即使在非QEMU方式
運行OP-TEE時,OP-TEE的驅動和tee_supplicant同
樣會被掛載和啟動,這屬于運行OP-TEE不可或缺
的一部分。第6章 安全引導功能及ATF的啟動過
程
安全引導(Secure Boot)功能是指在系統(tǒng)的整
個啟動過程中,使用鏈式驗證電子簽名的方式來驗
證系統(tǒng)中重要鏡像文件的可靠性,然后再加載鏡像
文件的引導過程。安全引導功能可以保護二級廠商
系統(tǒng)的獨立性和完整性。在ARMv8架構中ARM提
供了ARM可信固件(ATF)。Bootloader、Linux內
核、TEE OS的啟動都由ATF來加載和引導。對于
ARMv8,Bootloader、Linux內核和TEE OS鏡像文
件的驗簽工作都是在ATF中完成的。本章將介紹安
全引導功能的原理以及ATF的啟動過程。6.1 安全引導的作用
安全引導可用于保證系統(tǒng)的完整性,防止系統(tǒng)
中重要鏡像文件被破壞或替換。一般情況下,安全
引導需要保護系統(tǒng)的BootLoader鏡像文件、TEE鏡
像文件、Linux內核鏡像文件、Recover鏡像文件以
及在ARMv8中使用的ATF鏡像文件。將TEE鏡像文
件的加載操作加入安全引導功能中可阻止黑客通過
替換TEE鏡像文件的方式來竊取被TEE保護的重要
資料。當前使用ARM芯片的系統(tǒng)中大部分使能了安
全引導功能,該功能對于用戶的最直接感受就是,當用戶非法刷入其他廠商的ROM后手機無法正常啟
動,這是因為非法刷機將導致系統(tǒng)中的重要鏡像文
件被替換,系統(tǒng)在啟動過程中對鏡像文件的電子驗
簽失敗,如果BootLoader驗證失敗,則系統(tǒng)在進入
BootLoader階段之前就會掛死。6.2 安全引導的原理
安全引導功能的原理就是采用鏈式驗簽的方式
啟動系統(tǒng),也就是在系統(tǒng)啟動過程中,在加載下一
個階段的鏡像之前都會對需要被加載的鏡像文件進
行電子驗簽,只有驗簽操作通過后,該鏡像才能被
加載到內存中,然后系統(tǒng)才會跳轉到下一個階段繼
續(xù)執(zhí)行,整個驗簽鏈中的任何一環(huán)驗簽失敗都會導
致系統(tǒng)掛死,系統(tǒng)啟動過程中的第一級驗簽操作是
由ChipRom來完成的。只要芯片一出廠,用戶就無
法修改固化在芯片中的這部分代碼,因此無法通過
修改第一級驗簽結果來關閉安全引導功能。而且驗
簽操作使用的RSA公鑰或者哈希值將會被保存在
OTPefuse中,該區(qū)域中的數據一般只有ChipRom和
TEE能夠讀取且無法被修改。RSA公鑰或者哈希值
將會在產品出廠之前被寫入到OTPefuse中,而且不
同廠商使用的密鑰會不一樣。
在谷歌的安全引導功能白皮書中提出了安全引
導功能實現方案的設計建議。谷歌建議將鏡像文件
的電子簽名信息和驗簽使用的RSA公鑰保存在電子
證書中,系統(tǒng)在啟動的過程中首先會驗證電子證書
的合法性,如果驗證通過則需從電子證書中獲取簽
名信息和RSA公鑰,然后再利用它們對鏡像文件進
行驗證。整個驗證過程就是先驗證證書,驗證證書通過后再去驗證鏡像文件的合法性。但是在實際實
現過程中,大多數芯片廠商是將簽名信息與需要被
驗簽的鏡像文件打包在一起,而RSA公鑰則會被打
包到執(zhí)行驗證操作的鏡像文件中。
不同廠商可能會對鏡像文件進行加密操作,使
保存在設備中的鏡像文件都是以密文的形式存在。
在啟動過程中,首先會驗證密文鏡像文件的合法性
然后再進行解密鏡像文件的操作,這些都完成后才
會將明文的鏡像文件加載到內存中然后再執(zhí)行跳轉
操作。6.2.1 ARMv7安全引導的過程
對于安全引導功能的實現和驗證過程各家芯片
公司的方案都不一樣,這是由該芯片的啟動流程以
及啟動所需鏡像文件來決定的,但都會遵循鏈式驗
簽啟動的原則。ARMv7架構并沒有使用ATF,系統(tǒng)
的啟動流程與以前一樣使用BootLoader來引導Linux
內核和TEE OS。安全引導的啟動流程如圖6-1所
示。圖6-1 安全引導的啟動流程
系統(tǒng)啟動過程使用鏈式驗簽的方式進行引導,其中任何一環(huán)驗簽失敗都會導致系統(tǒng)啟動失敗,為
防止通過替換ramdisk來修改根文件系統(tǒng)中的內容,一般將ramdisk與Linux內核打包在同一個鏡像文件
中,而且該鏡像文件需要待驗簽通過后才可被使
用。簽名信息一般是對鏡像文件的內容進行哈希計
算獲取摘要后再對該摘要使用RSA私鑰進行電子簽
名來獲得,驗證時同樣會計算需要被引導的鏡像文
件的摘要,然后使用該摘要、簽名信息以及RSA公
鑰進行RSA算法的驗證。6.2.2 ARMv8安全引導的過程
ARMv8架構之后ARM提供了ATF,BootLoader、TEE鏡像文件、Linux內核鏡像文件、recovery鏡像文件都是由ATF來進行引導和加載而
不是由ChipRom來完成的。ChipRom只會去驗證
ATF中bl1的合法性,后續(xù)引導過程同樣也是按照鏈
式驗簽的方式進行,符合TBBR規(guī)范。讀者可使用
git命令從gitHub上獲取ATF的所有源代碼[1]。在
ARMv8架構中整個安全引導的流程如圖6-2所示。圖6-2 ARMv8的Secure Boot流程
ARMv8架構中引入了ATF,同時在ATF中提供
了安全引導的功能,BootLoader鏡像、Linux內核、recovery鏡像和TEE OS鏡像文件的簽名方式都由
ATF決定。當然開發(fā)者也可以對ATF進行定制化,修改ATF中的驗簽過程,但是修改后的驗簽方案需
要符合TBBR規(guī)范。
[1] ATF的git倉庫鏈接可參閱ATF源代碼鏈接:
https:github.comlinaro-swgarm-trusted-firmware。6.3 ATF的啟動過程
ATF的啟動過程根據ARMv8的運行模式
(AArch32AArch64)會有所不同,但基本一致。
在AArch32中是不會去加載bl31而是將EL3或者
Monitor模式的運行代碼保存在bl32中執(zhí)行。在
AArch64中,ATF的完整啟動流程如圖6-3所示。
圖6-3 AArch64模式的ATF啟動流程
在上述啟動過程中,從一個鏡像跳轉到另外一
個鏡像文件執(zhí)行的方式各不相同,以下為鏡像跳轉的過程和方式說明。
1.bl1跳轉到bl2執(zhí)行
在bl1完成了將bl2鏡像文件加載到RAM中的操
作、中斷向量表的設定以及其他CPU相關設定后,bl1_main函數會解析出bl2鏡像文件的描述信息,獲
取入口地址,并設定下一個階段的cpu上下文。這
些操作完成之后,調用el3_exit函數來實現bl1到bl2
的跳轉,進入bl2中開始執(zhí)行。
2.bl2跳轉到bl31執(zhí)行
在bl2中將會加載bl31、bl32、bl33的鏡像文件
到對應權限的內存中,并將該三個鏡像文件的描述
信息組成一個鏈表保存起來,以備bl31啟動bl32和
bl33使用。在AArch64中,bl31為EL3的執(zhí)行軟件,其運行時的主要功能是對安全監(jiān)控模式調用
(smc)指令和中斷處理,運行在ARM的Monitor模
式中。
bl32一般為TEE OS鏡像文件,本章以OP-TEE
為例進行說明。
bl33為正常世界狀態(tài)的鏡像文件,例如uboot、EKD2等。當前該部分為BootLoader部分的鏡像文
件,再由BootLoader來啟動Linux內核鏡像。從bl2跳轉到bl31是通過帶入bl31的入口點信息
作為參數,然后調用安全監(jiān)控模式調用指令,觸發(fā)
在bl1中設定的安全監(jiān)控模式調用請求,該請求處理
完成后會將中央處理器的執(zhí)行權限交給bl31,并跳
轉到bl31中去執(zhí)行。
3.bl31跳轉到bl32執(zhí)行
在bl31中會執(zhí)行runtime_service_inti函數,該函
數會調用注冊到EL3中所有服務的初始化函數,其
中有一個服務項就是TEE服務,該服務項的初始化
函數會將TEE OS的初始化函數賦值給bl32_init變
量,當所有服務項執(zhí)行完初始化后,在bl31中會調
用bl32_init執(zhí)行的函數來跳轉到TEE OS中并開始執(zhí)
行TEE OS的啟動。
4.bl31跳轉到bl33執(zhí)行
當TEE-OS鏡像啟動完成后會觸發(fā)一個ID為
TEESMC_OPTEED_RETURN_ENTRY_DONE的安
全監(jiān)控模式調用,該調用是用來告知EL3 TEE OS
鏡像已經完成了初始化,然后將CPU的狀態(tài)恢復到
bl31_init的位置繼續(xù)執(zhí)行。
bl31通過遍歷在bl2中記錄的所有鏡像信息的鏈
表來找到需要執(zhí)行的bl33的鏡像。然后通過獲取到bl33鏡像的信息,設定下一個階段的CPU上下文, ......
手機安全和可信應用開發(fā)指南:TrustZone
與OP-TEE技術詳解
帥峰云 黃騰 宋洋 編著
ISBN:978-7-111-60956-8
本書紙版由機械工業(yè)出版社于2018年出版,電子版
由華章分社(北京華章圖文信息有限公司,北京奧
維博世圖書發(fā)行有限公司)全球范圍內制作與發(fā)
行。
版權所有,侵權必究
客服熱線:+ 86-10-68995265
客服信箱:service@bbbvip.com
官方網址:www.hzmedia.com.cn
新浪微博 @華章數媒
微信公眾號 華章電子書(微信號:hzebook)目錄 推薦序
前言
致謝
第一篇 基礎技術篇
第1章 可信執(zhí)行環(huán)境
1.1 系統(tǒng)存在的安全問題
1.2 TEE如何保護數據安全
1.3 現有TEE解決方案
1.3.1 智能手機領域的TEE
1.3.2 智能電視領域的TEE
1.3.3 IoT領域及其他領域的TEE
1.4 為什么選擇OP-TEE
第2章 ARM的TrustZone技術
2.1 TrustZone技術
2.1.1 片上系統(tǒng)硬件框架
2.1.2 ARMv7架構的TrustZone技術
2.1.3 ARMv8架構的TrustZone技術
2.2 ARM安全擴展組件
2.2.1 AXI總線上安全狀態(tài)位的擴展
2.2.2 AXI-to-APB橋的作用
2.2.3 TrustZone地址空間控制組件
2.2.4 TrustZone內存適配器組件
2.2.5 TrustZone保護控制器組件
2.2.6 TrustZone中斷控制器組件2.2.7 Cache和MMU的擴展
2.3 TrustZone技術對資源隔離的實現
2.3.1 中斷源的隔離
2.3.2 片上RAM和片上ROM的隔離
2.3.3 片外DRAM的隔離
2.3.4 外圍設備的隔離
2.4 小結
第3章 ARM可信固件
3.1 為什么使用ATF
3.2 ATF的主要功能
3.3 ATF與TEE的關系
3.4 小結
第4章 OP-TEE運行環(huán)境的搭建及編譯
4.1 獲取OP-TEE代碼并搭建運行環(huán)境
4.1.1 OP-TEE開發(fā)環(huán)境的搭建
4.1.2 獲取OP-TEE的源代碼
4.1.3 獲取編譯OP-TEE的toolchain
4.1.4 編譯QEMU
4.1.5 運行OP-TEE
4.1.6 運行xtest和
optee_example_hello_world
4.2 運行CA和TA示例
4.2.1 示例代碼的獲取和集成
4.2.2 目錄和文件創(chuàng)建
4.2.3 CA端代碼的修改
4.2.4 TA端代碼的修改4.2.5 TA和CA在OP-TEE的集成
4.3 OP-TEE源代碼結構
4.4 OP-TEE編譯
4.4.1 編譯目標的依賴關系
4.4.2 bios.bin鏡像的生成過程
4.4.3 run-only目標的執(zhí)行
4.5 小結
第二篇 系統(tǒng)集成篇
第5章 QEMU運行OP-TEE的啟動過程
5.1 bios.bin的入口函數
5.2 OP-TEE鏡像的加載和啟動
5.3 Linux內核鏡像的加載和啟動
5.4 rootfs的掛載
5.5 OP-TEE驅動的啟動
5.6 tee_supplicant的啟動
5.7 小結
第6章 安全引導功能及ATF的啟動過程
6.1 安全引導的作用
6.2 安全引導的原理
6.2.1 ARMv7安全引導的過程
6.2.2 ARMv8安全引導的過程
6.3 ATF的啟動過程
6.3.1 ATF中bl1的啟動
6.3.2 ATF中bl2的啟動
6.3.3 ATF中bl31的啟動
6.3.4 ATF中bl32的啟動6.3.5 ATF啟動過程小結
6.4 小結
第7章 OP-TEE OS的啟動過程
7.1 OP-TEE鏡像啟動過程
7.1.1 OP-TEE OS的入口函數
7.1.2 OP-TEE的內核初始化過程
7.1.3 OP-TEE服務項的啟動
7.1.4 OP-TEE驅動的掛載
7.2 ARM64位與ARM32位OP-TEE啟動過程的
差異
7.3 小結
第8章 OP-TEE在REE側的上層軟件
8.1 OP-TEE的軟件框架
8.2 REE側libteec庫提供的接口
8.2.1 libteec庫提供的接口說明
8.2.2 CA調用libteec庫中接口的流程
8.3 REE側的守護進程——tee_supplicant
8.3.1 tee_supplicant編譯生成和自啟動
8.3.2 tee_supplicant入口函數
8.3.3 tee_supplicant存放RPC請求的結構體
8.3.4 tee_supplicant中的無限循環(huán)
8.3.5 tee_supplicant獲取TA的RPC請求
8.3.6 TA RPC請求的解析
8.3.7 RPC請求的處理
8.3.8 回復RPC請求
8.4 各種RPC請求的處理8.4.1 加載TA鏡像
8.4.2 操作REE側的文件系統(tǒng)
8.4.3 操作RPMB
8.4.4 分配共享內存
8.4.5 釋放共享內存
8.4.6 記錄程序執(zhí)行效率
8.4.7 網絡套接字操作
8.5 小結
第9章 REE側OP-TEE的驅動
9.1 OP-TEE驅動模塊的編譯保存
9.2 REE側OP-TEE驅動的加載
9.2.1 設備號和class的初始化
9.2.2 optee_driver_init函數
9.2.3 掛載驅動的probe操作
9.2.4 獲取切換到Monitor模式或EL3的接口
9.2.5 驅動版本和API版本校驗
9.2.6 判定OP-TEE是否預留共享內存空間
9.2.7 配置驅動與OP-TEE之間的共享內存
9.2.8 分配和設置tee0和teepriv0的設備信息
結構體變量
9.2.9 tee0和teepriv0設備的注冊
9.2.10 請求隊列的初始化
9.2.11 使能TEE中共享內存的緩存
9.2.12 OP-TEE驅動掛載的總結
9.3 REE側用戶空間對驅動的調用過程
9.4 OP-TEE驅動中重要的結構體變量9.4.1 OP-TEE驅動的file_operation結構體變
量tee_fops
9.4.2 tee0設備的tee_driver_ops結構體變量
optee_ops
9.4.3 teepriv0設備的操作結構體變量
optee_supp_ops
9.4.4 共享驅動緩存操作變量
tee_shm_dma_buf_ops
9.5 OP-TEE驅動與OP-TEE之間共享內存的注
冊和分配
9.6 libteec庫中的接口在驅動中的實現
9.6.1 libteec庫中的open操作
9.6.2 libteec庫中的release操作
9.6.3 libteec執(zhí)行get_version操作
9.6.4 libteec庫中的open session操作
9.6.5 libteec庫中的invoke操作
9.7 tee_supplicant接口在驅動中的實現
9.7.1 接收OP-TEE的RPC請求
9.7.2 獲取OP-TEE的RPC請求
9.7.3 OP-TEE的RPC請求的返回
9.8 小結
第三篇 OP-TEE內核篇
第10章 ARM核安全態(tài)和非安全態(tài)間的切換
10.1 ARMv7基本知識
10.1.1 ARMv7運行模式擴展
10.1.2 安全狀態(tài)位擴展10.1.3 重要寄存器
10.1.4 安全監(jiān)控模式調用的匯編指令
10.2 Monitor模式下的處理過程
10.2.1 Monitor模式對安全監(jiān)控模式調用的
處理
10.2.2 正常世界狀態(tài)中觸發(fā)安全監(jiān)控模式
調用的處理過程
10.2.3 安全世界狀態(tài)中觸發(fā)安全監(jiān)控模式
調用的處理過程
10.3 ARMv8基本知識
10.3.1 ARM核運行模式的新定義
10.3.2 ARMv8安全狀態(tài)位擴展
10.3.3 寄存器資源
10.3.4 安全監(jiān)控模式調用匯編指令
10.4 EL3的處理過程
10.4.1 ATF中EL3異常向量表的注冊
10.4.2 EL3處理安全監(jiān)控模式調用的流程
10.4.3 安全世界狀態(tài)中觸發(fā)安全監(jiān)控模式
調用的處理過程
10.4.4 正常世界狀態(tài)中觸發(fā)安全監(jiān)控模式
調用的處理過程
10.4.5 opteed_smc_handler函數
10.5 小結
第11章 OP-TEE對安全監(jiān)控模式調用的處理
11.1 OP-TEE的線程向量表
11.2 ARMv7中Monitor模式對安全監(jiān)控模式調用的處理
11.3 ARMv8中EL3處理安全監(jiān)控模式調用的
實現
11.4 OP-TEE對快速安全監(jiān)控模式調用的處理
11.5 OP-TEE對標準安全監(jiān)控模式調用的處理
11.5.1 OP-TEE對RPC請求返回操作的處理
11.5.2 OP-TEE對libteec庫觸發(fā)的安全監(jiān)控
模式調用的處理
11.6 小結
第12章 OP-TEE對中斷的處理
12.1 系統(tǒng)的中斷處理
12.2 中斷控制器
12.2.1 GIC寄存器
12.2.2 ARMv7 SCR寄存器的設定
12.2.3 ARMv8 SCR寄存器的設定
12.2.4 GICv2架構
12.2.5 GICv3架構
12.3 異常向量表配置
12.3.1 ARMv7中Monitor模式的異常向量表
12.3.2 ARMv8中EL3階段的異常向量表
12.3.3 OP-TEE異常向量的配置
12.4 OP-TEE的線程向量表
12.5 全局handle變量的初始化
12.6 ARMv7 Monitor對FIQ事件的處理
12.7 ARMv8 EL3階段對FIQ事件的處理
12.8 OP-TEE對FIQ事件的處理12.9 OP-TEE對IRQ事件的處理
12.10 小結
第13章 OP-TEE對TA操作的各種實現
13.1 創(chuàng)建會話在OP-TEE中的實現
13.1.1 靜態(tài)TA的創(chuàng)建會話操作
13.1.2 動態(tài)TA的創(chuàng)建會話操作
13.2 調用TA命令操作在OP-TEE中的實現
13.2.1 靜態(tài)TA的調用命令操作的實現
13.2.2 動態(tài)TA的調用命令操作實現
13.3 關閉會話操作在OP-TEE中的實現
13.3.1 靜態(tài)TA的關閉會話操作
13.3.2 動態(tài)TA的關閉會話操作
13.4 小結
第14章 OP-TEE的內存和緩存管理
14.1 物理內存和緩存數據的硬件安全保護
14.1.1 內存設備安全區(qū)域的隔離
14.1.2 MMU和緩存中數據的安全隔離
14.2 ARM核對內存的訪問
14.2.1 ARM核獲取內存數據的過程
14.2.2 獲取緩存數據的過程
14.2.3 緩存和TLB中條目的一致性
14.3 OP-TEE對內存區(qū)域的管理
14.3.1 OP-TEE中內存區(qū)域的類型
14.3.2 內存區(qū)域編譯設置
14.4 MMU的初始化和映射頁表
14.4.1 MMU的初始化入口函數14.4.2 物理地址到虛擬地址表的建立
14.4.3 MMU轉換頁表的創(chuàng)建
14.4.4 MMU寄存器配置
14.5 OP-TEE內存安全權限檢查
14.6 系統(tǒng)的共享內存
14.6.1 共享內存的配置
14.6.2 OP-TEE驅動與OP-TEE之間的共享
內存
14.6.3 OP-TEE內核空間與用戶空間之間的
共享內存
14.7 數據是否需要寫入Cache
14.8 小結
第15章 OP-TEE中的線程管理
15.1 OP-TEE中的線程
15.2 線程狀態(tài)切換
15.2.1 Free態(tài)到Active態(tài)的實現
15.2.2 Active態(tài)到Suspend態(tài)的實現
15.2.3 Suspend態(tài)到Active態(tài)的實現
15.2.4 Active態(tài)到Free態(tài)的實現
15.3 線程運行時的資源
15.3.1 線程數據結構體
15.3.2 OP-TEE分配的內核棧
15.3.3 線程運行于用戶空間的資源
15.3.4 tee_ta_session結構體
15.4 線程運行時資源的使用關系
15.5 OP-TEE中線程的調度15.6 線程的死鎖
15.6.1 死鎖的原理
15.6.2 防止死鎖
15.7 小結
第16章 OP-TEE的系統(tǒng)調用
16.1 OP-TEE系統(tǒng)調用的作用
16.2 OP-TEE系統(tǒng)調用的實現
16.2.1 系統(tǒng)調用的整體流程
16.2.2 系統(tǒng)調用的定義
16.2.3 系統(tǒng)調用表tee_sv_syacall_table
16.3 小結
第17章 OP-TEE的IPC機制
17.1 IPC機制的作用
17.2 IPC機制的原理
17.3 IPC的實現
17.3.1 TA調用其他TA的實現
17.3.2 TA調用系統(tǒng)服務和安全驅動的實現
17.3.3 TA對密碼學系統(tǒng)服務的調用實現
17.3.4 對SE功能模塊進行操作的系統(tǒng)服務
17.3.5 加載TA鏡像的系統(tǒng)服務
17.4 小結
第四篇 應用開發(fā)篇
第18章 TA鏡像的簽名和加載
18.1 TA鏡像文件的編譯和簽名
18.1.1 TA鏡像文件的編譯
18.1.2 對TA鏡像文件的簽名18.2 TA鏡像的加載
18.2.1 REE側獲取TA鏡像文件的內容
18.2.2 加載TA鏡像的RPC請求
18.2.3 RPC請求的發(fā)送
18.2.4 讀取TA鏡像文件內容到共享內存
18.3 TA鏡像合法性的驗證
18.3.1 驗證TA鏡像合法性使用的RSA公鑰
的產生和獲取
18.3.2 TA鏡像文件合法性的檢查
18.4 加載TA鏡像到OP-TEE的用戶空間
18.5 TA運行上下文的初始化
18.6 小結
第19章 OP-TEE中的密碼學算法
19.1 算法使用示例
19.1.1 示例代碼獲取和集成
19.1.2 板級編譯文件的修改
19.1.3 通用編譯文件的修改
19.1.4 編譯運行
19.2 OP-TEE中的SHA算法
19.2.1 TA中使用SHA算法的實現
19.2.2 SHA算法實現接口說明
19.3 OP-TEE中的AES算法
19.3.1 TA中使用AES算法的實現
19.3.2 AES算法實現接口說明
19.4 OP-TEE中的RSA算法
19.4.1 TA中使用RSA算法的實現19.4.2 RSA算法實現接口說明
19.5 小結
第20章 OP-TEE的安全存儲
20.1 安全存儲簡介
20.2 安全存儲使用示例
20.2.1 示例代碼獲取和集成
20.2.2 板級編譯文件的修改
20.2.3 通用編譯文件的修改
20.2.4 編譯運行
20.3 安全存儲功能使用的密鑰
20.3.1 安全存儲密鑰
20.3.2 可信應用的存儲密鑰
20.3.3 文件加密密鑰
20.4 安全文件、dirf.db文件的數據格式和操
作過程
20.4.1 dirf.db文件和安全文件的格式
20.4.2 安全存儲功能中使用的重要結構體
20.4.3 安全存儲中的文件節(jié)點組成
20.4.4 查詢安全文件中的特定數據塊
20.5 安全存儲文件的創(chuàng)建
20.5.1 安全存儲軟件框架
20.5.2 dirf.db文件的創(chuàng)建
20.5.3 安全文件的創(chuàng)建
20.6 安全文件的打開操作
20.6.1 安全文件的打開
20.6.2 打開dirf.db文件并建立節(jié)點樹20.6.3 安全文件在datatee目錄下的文件編
號
20.6.4 打開特定安全文件
20.7 安全文件的讀寫操作
20.7.1 安全文件中數據的讀取
20.7.2 安全文件中數據的寫入
20.8 安全文件中數據的加解密
20.8.1 各種類型數據的組成及作用
20.8.2 元數據的加密
20.8.3 數據塊區(qū)域的加密策略
20.9 小結
第21章 可信應用及客戶端應用的開發(fā)
21.1 TA及CA的基本概念
21.2 GP標準
21.3 GP標準對TA屬性的定義
21.4 GP標準定義的接口
21.4.1 GP定義的客戶端接口
21.4.2 GP定義的內部接口
21.5 TA和CA的實現
21.5.1 建立CA和TA的目錄結構
21.5.2 CA代碼的實現
21.5.3 TA代碼的實現
21.6 TA和CA的集成
21.6.1 CA和TA的Makefile的修改
21.6.2 OP-TEE中comm.mk和xxx.mk文件的
修改21.7 TA和CA的調試
21.8 TA和CA的使用
21.9 小結
第22章 安全驅動的開發(fā)
22.1 安全設備的硬件安全隔離
22.2 OP-TEE中安全驅動的框架
22.2.1 系統(tǒng)服務層
22.2.2 驅動層
22.2.3 驅動文件在源代碼中的位置
22.3 安全驅動的開發(fā)過程和示例
22.3.1 示例代碼獲取和集成
22.3.2 驅動實現
22.3.3 添加系統(tǒng)服務
22.3.4 添加系統(tǒng)調用
22.3.5 測試使用的TA和CA
22.4 安全驅動示例的測試
22.5 小結
第23章 終端密鑰在線下發(fā)系統(tǒng)
23.1 密鑰在線下發(fā)系統(tǒng)的框架
23.2 密鑰在線下發(fā)的數據包格式
23.3 密鑰在線下發(fā)系統(tǒng)示例
23.3.1 示例代碼獲取和集成
23.3.2 板級編譯文件的修改
23.3.3 通用編譯文件的修改
23.3.4 編譯運行
23.4 離線工具的使用23.5 小結
第24章 基于OP-TEE的在線支付系統(tǒng)
24.1 在線支付系統(tǒng)的基本框架
24.2 可信通信通道
24.3 數據交互協(xié)議
24.3.1 數據頭部區(qū)域
24.3.2 數據區(qū)域
24.3.3 電子簽名區(qū)域
24.3.4 交互數據包的格式
24.4 在線支付系統(tǒng)示例的實現
24.4.1 第一次握手請求
24.4.2 第二次握手數據的解析
24.4.3 第三次握手請求
24.4.4 支付請求
24.4.5 支付反饋
24.5 示例的集成
24.5.1 示例代碼的獲取和集成
24.5.2 板級編譯文件的修改
24.5.3 通用編譯文件的修改
24.5.4 編譯運行
24.5.5 示例支持的命令說明
24.5.6 服務器端工具
24.6 組包操作嵌入內核
24.7 支付系統(tǒng)與生物特征的結合
24.8 小結
第25章 TEE可信應用的使用領域25.1 在線支付
25.2 數字版權保護
25.3 身份驗證
25.4 其他領域
術語表推薦序
近年來隨著指紋支付的盛行,如支付寶、微信
支付等,可信執(zhí)行環(huán)境(Trusted Execution
Environment,TEE)被廣泛應用在手機、平板電腦
等移動終端設備中。尤其是近年來谷歌對系統(tǒng)安全
問題越來越重視,可信執(zhí)行環(huán)境已成為谷歌提升系
統(tǒng)安全性的重要技術之一,包含為人熟知的
keymaster、gatekeeper等,未來在Android P上還會
引入基于TUI(Trusted User Interface)衍生的
Confirmation UI,這將會為使用者提供更好的安全
體驗。
可信執(zhí)行環(huán)境是一個典型的軟硬件協(xié)同合作的
概念,基于ARM的TrustZone技術為系統(tǒng)提供資源
的物理隔離,將系統(tǒng)執(zhí)行環(huán)境區(qū)隔為安全區(qū)域和非
安全區(qū)域。開發(fā)者通過使用安全操作系統(tǒng)(secure
OS)提供的API開發(fā)更多的可信應用來實現特定的
安全功能。系統(tǒng)的安全是環(huán)環(huán)相扣的信任鏈,從設
備開機的安全引導到安全操作系統(tǒng)的安全性驗證,一直到軟件開發(fā)者開發(fā)的軟件安全性驗證,每層相
扣,而可信執(zhí)行環(huán)境為可信應用提供了一個基礎且
可信任的執(zhí)行環(huán)境。
未來TEE的發(fā)展方向是多元的,TEE的應用也會進入更多的產業(yè),除了目前大熱的指紋識別之
外,系統(tǒng)也會引入更多的生物識別技術,如虹膜與
人臉識別,從攝像頭獲取圖像到識別演算的整個過
程都會在TEE中完成。此外TUI也是重要的方向之
一,使用者如何確認所見即所支付,確認的支付金
額或轉賬賬號不會被別人攻擊或修改,都是相當重
要的安全需求。除了移動終端設備之外,車載系統(tǒng)
和IoT設備也都有對應的安全需求,因此在可遇見
的未來,TEE將會被廣泛應用到不同領域、不同的
電子設備中。
此外,安全應用的開發(fā)者如何將安全應用廣泛
部署到不同的設備中,以及如何安全升級它們也相
當重要。當發(fā)現了軟件漏洞,如何第一時間更新安
全應用并避免版本回滾的攻擊,是系統(tǒng)安全的一個
重要議題,目前商用TEE的生態(tài)、安全應用的簽名
密鑰都掌握在設備制造商手中,而安全應用的獨立
在線下發(fā)和更新,將是未來的重要技術發(fā)展方向。
機緣巧合,我認識峰云已經有相當久的時間
了,他對TEE的了解相當深入,也相當用心地完成
了該書,遇到有疑問與不理解的地方,他會想方設
法地找出答案,他的專業(yè)與用心深受大家的肯定與
贊賞。本書涵蓋了TEE的硬件和軟件知識,通過
OP-TEE開源項目的協(xié)助,讀者可以通過理論與實
踐的結合,深入理解TEE的原理、設計與應用。期望通過本書的出版,能夠讓更多人了解與接觸TEE
的相關知識,進而發(fā)現更多的應用場景,享受更多
的安全服務,讓未來的生活在因為科技更方便的同
時,使用者的隱私與安全也能得到保護。
邱國政(Koshi)
Trustonic中國OEM經理前言
早在2014年,投資過Facebook、Skype、Twitter等的風投公司創(chuàng)始人安德森就說:“移動正
在吞噬這個世界”(mobile is eating the world)。這
毫不夸張,全球范圍內移動設備的數量已經超過了
世界人口的總和。在如今信息化技術高速發(fā)展的時
代,人們的生活越來越離不開智能手機,越來越多
的業(yè)務從原先復雜的流程演變到現在只需要簡單地
在手機上按幾個按鍵。技術是一把雙刃劍,總能給
人帶來難以想象的便利,但便利總是伴隨著用戶隱
私的泄漏、身份認證的濫用等一系列的安全風險。
據著名安全漏洞報告機構FreeBuf 2017年度移動應
用程序安全漏洞與數據泄漏狀況報告指出,多達
88%的金融類App存在內存敏感數據泄漏問題,娛
樂類移動應用程序更是安全漏洞的重災區(qū),社交類
App被仿冒的概率比其他類別平均高出10倍以上。
如何保障移動設備的安全,提高安全認證程序的可
靠性,一直是近幾年的熱門話題。
由嵌入式處理器最大的設計商ARM公司提出
的硬件虛擬化擴展技術TrustZone,發(fā)展到現在已經
有十余年的光景,如今已成為智能手機平臺不可或
缺的部分。從Android 7.0開始,谷歌就明確表示,Android設備上有關生物特征(指紋、虹膜等)識別的方案一定要基于可信執(zhí)行環(huán)境(Trust
Execution Environment,TEE)來實現。TEE就是基
于TrustZone技術建立的具有更高安全級別的可信執(zhí)
行環(huán)境,運行在TEE環(huán)境下的應用稱為可信應用程
序(Trusted Application,TA)。隨著TEE可信應用
開發(fā)的API的普及,國內越來越多的手機廠商開始
集成TEE以及相關的可信應用。TEE環(huán)境的提供商
也越來越多,從先前國外的Trustonic TEE、高通
QSEE到現在國內的豆莢、華為、瓶缽等,可以說
TEE的技術開發(fā)門檻在降低,應用熱度在提高。在
眾多TEE產品方案中,有一個優(yōu)秀的開源方案逐漸
進入人們的視野,那就是OP-TEE。OP-TEE(Open
Platform Trusted Execution Environment)由ST-
Ericsson創(chuàng)建,由STMicroelectronics維護,2014年
ARM的開源社區(qū)Linaro將OP-TEE方案開源。截至
目前,OP-TEE一直是Linaro社區(qū)在維護的核心安全
項目之一。目前看來,進入TEE領域最好的方式就
是學習成熟的OP-TEE方案。作者便是在學習OP-
TEE的過程中完成了本書,旨在為后繼的入門者掃
除一些障礙。
本書組織結構
本書將采取由淺入深的方式介紹TrustZone技術
的原理、OP-TEE的整體架構及其主要功能模塊的
原理,同時介紹如何基于OP-TEE進行可信應用、客戶端應用(Client Application,CA)、安全驅動
等功能的開發(fā)。
本書主要分為四篇,總計25章,各篇的主要內
容分別如下。
·第一篇,基礎技術篇(第1章~第4章),包
含TrustZone技術的背景和實現原理、系統(tǒng)基本框架
以及OP-TEE環(huán)境的搭建。
·第二篇,系統(tǒng)集成篇(第5章~第9章),分
析OP-TEE在REE和TEE中各個組件的作用和聯(lián)系,對于有一定嵌入式以及LinuxAndroid開發(fā)經驗的讀
者,該篇實質上給將OP-TEE集成到基于
ARMv7ARMv8處理器的開發(fā)平臺打下基礎。
·第三篇,OP-TEE內核篇(第10章~第17
章),包含OP-TEE內核的中斷處理、線程管理和
通信等主要功能的實現原理,使讀者對TEE OS的
架構設計有進一步認識。
·第四篇,應用開發(fā)篇(第18章~第25章),介紹基于OP-TEE在加密、解密、安全存儲等方面
的實際應用,以及如何開發(fā)基于OP-TEE的可信應
用程序。如果對OP-TEE有一定了解的讀者希望通
過實踐開發(fā)來了解TEE的工作原理,可以直接從應用開發(fā)篇學習。
OP-TEE的代碼量遠沒有Linux內核大,但其涉
及的設計之復雜、模塊之豐富也不是本書能完全涵
蓋的。我們的初衷是希望通過本書對重要模塊的代
碼和流程進行分析,使讀者對OP-TEE的架構有整
體的認識,之后看到其他部分也能做到舉一反三。
本書的主要代碼均引用自GitHub上OP-TEE開
源項目的源代碼(鏈接:https:github.comOP-
TEEoptee_os),作者在翻譯了一些代碼英文注釋
的基礎上根據自己的理解對部分代碼補充了更多的
注釋。如果讀者對書中代碼的中文注釋有疑問,可
參考上述鏈接中的原始代碼和注釋。另外,OP-
TEE也有詳細的文檔資料(https:github.comOP-
TEEoptee_ostreemasterdocumentation),強烈建
議英文基礎好的讀者結合本書和官方文檔來學習。
如發(fā)現本書有紕漏和錯誤,或者需要改進之處,希
望讀者不吝指出。
本書特色
俗話說,基礎打不牢,學問攀不高。本書采取
自下而上的方式從硬件的角度介紹了TrustZone技
術,并結合源代碼逐步剖析了基于TrustZone技術的
OP-TEE實現。在技術深度上,本書從入門者的角度出發(fā)由淺入深,從最基礎的開發(fā)環(huán)境的搭建到最
終的OP-TEE OS的內部實現都進行了介紹;從內容
易讀性上來講,本書提供了基礎的示例代碼和各種
算法的使用示例,并給出了所有示例的源代碼鏈接
及操作的實驗步驟。相信讀者通過邊學習邊實踐的
方式閱讀完本書后,能夠掌握TrustZone技術的基礎
原理和使用OP-TEE進行實際的應用開發(fā)。
由于任何TEE方案的源代碼都屬于芯片廠商的
商業(yè)機密,外界無法一覽各TEE方案的實現原理,且TrustZone也是最近幾年才被正式商用的,所以網
上的資料較少。本書是作者基于多年的工作積累并
對實際工作過程中遇見的問題進行整理后形成的。
本書讀者對象
·手機、嵌入式系統(tǒng)和芯片開發(fā)者及技術支持
人員;
·手機和嵌入式系統(tǒng)安全與可信應用(支付系
統(tǒng)、多媒體及身份識別等)開發(fā)人員;
·相關專業(yè)安全技術研究者和大專院校學生;
·廣大關心安全技術的愛好者。致謝
從萌生寫本書的念頭到最終完成初稿共花了一
年零三個月,一路走來歷經波折,其間獲得了許多
朋友和老師的幫助,感恩這一切。感謝他們曾經的
陪伴和咖啡,讓我有勇氣將本書寫完。
感謝邱國政(Koshi)的指導以及他為本書擬
定的大綱,感謝他在寫作期間提供的耐心的釋疑解
惑,并在初稿完成后擠出寶貴的時間審閱全稿,提
出建設性的修改意見。
感謝段富剛師兄在寫作初期的建議、支持和鼓
勵,以及在后期審稿階段給出的修改意見,因您一
語,才使我嘗試將博文整理成書稿,使內容更加完
善和系統(tǒng)。
感謝樊鵬對本書稿件的審閱及結合自身在NXP
車載芯片上集成OP-TEE的實際工作經驗對本書提
供的寶貴建議。
感恩家人在寫作期間給予的理解和支持。感恩
沈雪亮和林先賢曾經的教導,感謝王佞姐平時的關
心,感謝黃誠、龔強強、徐貴友等好友在我撰寫本
書期間給予的無私幫助和真切鼓勵。感謝孟慶洋博士、黃冕博士、王子亮總監(jiān)、尉
魯飛師兄對本書內容的認可和推薦。感謝鄧仰東老
師和朱捷編輯在審稿期間給予的非常有益的建議和
指導,讓本書的內容更加豐富和嚴謹。
感謝張星茹在我考研時提供的幫助,感恩大學
那么一幫人,十年友誼一直未變。
感謝OP-TEE開源項目組的各位大牛,正是你
們的分享精神賦予了開發(fā)者涉足TrustZone這片神秘
領地和一探TEE具體實現原理的機會。
最后僅以此書紀念自己曾經的三十年,感恩生
命中遇見的每一個人、大學同學(于洋、郭成飛、吼哥、濤哥、胖胖、石頭、王健等一幫兄弟)、研
究生同學(劉峰、孫登高、夏軒、劉智、陳耀
闖),以及所有的朋友,是你們的出現讓我過去的
三十年不曾遺憾。第一篇 基礎技術篇
第1章 可信執(zhí)行環(huán)境
第2章 ARM的TrustZone技術
第3章 ARM可信固件
第4章 OP-TEE運行環(huán)境的搭建及編譯第1章 可信執(zhí)行環(huán)境
1.1 系統(tǒng)存在的安全問題
隨著移動通信和互聯(lián)網技術的飛速發(fā)展,智能
設備在各個領域扮演著越來越重要的角色。據統(tǒng)
計,在2017年,中國使用智能手機上網的用戶數已
達6億之多。此外,無人駕駛、物聯(lián)網、網絡電視
等也都與智能設備相關,或者本身就是智能設備,它們都會用到操作系統(tǒng)。然而由于一些黑客能夠破
解智能設備的root權限,進而盜取用戶數據或其他
關鍵信息,造成用戶數據的泄露或濫用。其次,如
果用戶的車載系統(tǒng)被黑客獲取控制權限,其人身安
全將無從保障。因此手機互聯(lián)網領域、電視領域、物聯(lián)網領域以及車載領域的安全越來越顯得重要。
再者,智能設備上各種應用不斷涌現,若開發(fā)
人員在開發(fā)這些應用時沒有針對安全進行加固保
護,則黑客可能會利用這些應用本身固有的安全漏
洞獲取智能設備操系統(tǒng)的root權限,輕松截獲用戶
的敏感數據。鑒于此,如何保障智能設備的安全變
得越來越重要。
那么,如何消除甚至杜絕這類威脅呢?除了提
高系統(tǒng)被破解的難度之外,最好還要在系統(tǒng)中提供一個相對可信賴的運行環(huán)境,使用戶的關鍵數據或
應用在這個相對可信賴的環(huán)境中使用和運行。這樣
一來,即便系統(tǒng)被攻破,入侵者也無法直接獲取用
戶的重要信息,用戶的信息安全也就實現了,這就
是可信執(zhí)行環(huán)境(Trusted Execution Environment,TEE)的主要作用和理念。1.2 TEE如何保護數據安全
為了給移動設備提供一個安全的運行環(huán)境,ARM從ARMv6的架構開始引入了TrustZone技術。
TrustZone技術將中央處理器(Central Processing
Unit,CPU)的工作狀態(tài)分為了正常世界狀態(tài)
(Normal World Status,NWS)和安全世界狀態(tài)
(Secure World Status,SWS)。支持TrustZone技
術的芯片提供了對外圍硬件資源的硬件級別的保護
和安全隔離。當CPU處于正常世界狀態(tài)時,任何應
用都無法訪問安全硬件設備,也無法訪問屬于安全
世界狀態(tài)下的內存、緩存(Cache)以及其他外圍
安全硬件設備。
TEE基于TrustZone技術提供可信運行環(huán)境,還
為開發(fā)人員提供了應用程序編程接口(Application
Programming Interface,API),以方便他們開發(fā)實
際應用程序。
在整個系統(tǒng)的軟件層面,一般的操作系統(tǒng)(如
Linux、Android、Windows等)以及應用運行在正
常世界狀態(tài)中,TEE運行在安全世界狀態(tài)中,正常
世界狀態(tài)內的開發(fā)資源相對于安全世界狀態(tài)較為豐
富,因此通常稱運行在正常世界狀態(tài)中的環(huán)境為豐
富執(zhí)行環(huán)境(Rich Execution Environment,REE),而可信任的操作系統(tǒng)以及上層的可信應用
(Trusted Application,TA)運行于安全世界狀
態(tài),運行在安全世界狀態(tài)中的系統(tǒng)就是前文提到的
TEE。
對CPU的工作狀態(tài)區(qū)分之后,處于正常世界狀
態(tài)中的Linux即使被root也無法訪問安全世界狀態(tài)中
的任何資源,包括操作安全設備、訪問安全內存數
據、獲取緩存數據等。這很像一個保險箱,不管保
險箱的外在環(huán)境是否安全,其內部的物件都有足夠
的安全性。這是因為CPU在訪問安全設備或者安全
內存地址空間時,芯片級別的安全擴展組件會去校
驗CPU發(fā)送的訪問請求的安全狀態(tài)讀寫信號位
(Non-secure bit,NS bit)是0還是1,以此來判定
當前CPU發(fā)送的資源訪問請求是安全請求還是非安
全請求。而處于非安全狀態(tài)的CPU將訪問指令發(fā)送
到系統(tǒng)總線上時,其訪問請求的安全狀態(tài)讀寫信號
位都會被強制設置成1,表示當前CPU的訪問請求
為非安全請求。而非安全請求試圖去訪問安全資源
時會被安全擴展組件認為是非法訪問的,于是就禁
止其訪問安全資源,因此該CPU訪問請求的返回結
果要么是訪問失敗,要么就是返回無效結果,這也
就實現了對系統(tǒng)資源硬件級別的安全隔離和保護。
在真實環(huán)境中,可以將用戶的敏感數據保存到
TEE中,并由可信應用(Trusted Application,TA)使用重要算法和處理邏輯來完成對數據的處理。當
需要使用用戶的敏感數據做身份驗證時,則通過在
REE側定義具體的請求編號(IDentity,ID)從TEE
側獲取驗證結果。驗證的整個過程中用戶的敏感數
據始終處于TEE中,REE側無法查看到任何TEE中
的數據。對于REE而言,TEE中的TA相當于一個黑
盒,只會接受有限且提前定義好的合法調用,而至
于這些合法調用到底是什么作用,會使用哪些數
據,做哪些操作在REE側是無法知曉的。如果在
REE側發(fā)送的調用請求是非法請求,TEE內的TA是
不會有任何的響應或是僅返回錯誤代碼,并不會暴
露任何數據給REE側。1.3 現有TEE解決方案
TEE是一套完整的安全解決方案,主要包含正
常世界狀態(tài)的客戶端應用(Client Application,CA)、安全世界狀態(tài)的可信應用,可信硬件驅動
(Secure Driver,SD)以及可信內核系統(tǒng)(Trusted
Execution Environment Operation System,TEE
OS),其系統(tǒng)配置、內部邏輯、安全設備和安全資
源的劃分是與CPU的集成電路(Integrated Circuit,IC)設計緊密掛鉤的,使用ARM架構設計的不同
CPU,TEE的配置完全不一樣。國內外針對不同領
域的CPU也具有不同的TEE解決方案。
國內外各種TEE解決方案一般都遵循
GP(Global Platform)規(guī)范進行開發(fā)并實現相同的
API。GP規(guī)范規(guī)定了TEE解決方案的架構以及供TA
開發(fā)使用的API原型,開發(fā)者可以使用這些規(guī)定的
API開發(fā)實際的TA并能使其正常運行于不同的TEE
解決方案中。1.3.1 智能手機領域的TEE
智能手機領域的芯片廠商眾多,國外有高通
(Qualcomm)、三星(Samsung)、LG,國內有
展訊、聯(lián)發(fā)科(MediaTek)、威盛電子(VIA)、華為海思(Hisilicon)等,目前手機廠商和芯片廠
商支持的TEE解決關系如圖1-1所示。圖1-1 TEE解決方案關系
各家TEE解決方案的內部操作系統(tǒng)的邏輯會不一樣,但都能提供GP規(guī)范規(guī)定的API,對于二級廠
商或TA開發(fā)人員來說接口都是統(tǒng)一的。這些TEE解
決方案在智能手機領域主要用于實現在線支付(如
微信支付、支付寶支付)、數字版權保護(DRM、Winevine Level 1、China DRM)、用戶數據安全保
護、安全存儲、指紋識別、虹膜識別、人臉識別等
其他安全需求。這樣可以降低用戶手機在被非法
root之后帶來的威脅。
Google規(guī)定在Android M之后所有的Android設
備在使用指紋數據時都需要用TEE來進行保護,否
則無法通過Google的CTS認證授權,另外Android也
建議使用硬件Keymaster和gatekeeper來強化系統(tǒng)安
全性。1.3.2 智能電視領域的TEE
當前的智能電視領域大多是使用Android系統(tǒng)
來實現的,為保護二級廠商的視頻源數據以及各廠
家用戶會員權益不被盜取,需要使用TEE來實現數
字版權保護、會員鑒權、用戶賬號信息保護等安全
功能,而TEE方案一般都是由電視芯片廠商提供
的,且所有的TEE源代碼都不對外公開,即使是二
級廠商也無法獲取到TEE的源代碼。在我國的智能
電視領域,智能電視芯片主要有兩家:星辰半導體
(Mstar)和華為海思,兩家廠商使用的TEE方案都
不一樣。
Mstar早期的TEE方案是在CPU的一個類似于單
片機的核上運行Nuttx系統(tǒng)作為TEE OS來實現TEE
方案的,但最新的Mstar芯片已經改用OP-TEE方案
來實現TEE解決方案。
華為海思的安全操作系統(tǒng)(Secure Operating
System,Secure OS)是按照GP規(guī)范自主研發(fā)的
TEE解決方案,其手機芯片和智能電視芯片都是使
用這個TEE方案。華為海思的TEE增加了權限校驗
功能(類似于白名單機制),即在使用華為海思的
TEE方案提供的API實現特定安全功能的TA時,需
要將調用該TA對應的CA接口的進程或者服務的相關信息提前注冊到TEE后方能正常使用,否則會導
致調用失敗。1.3.3 IoT領域及其他領域的TEE
物聯(lián)網(Internet of Thing,IoT)領域和車載
系統(tǒng)領域將會是未來TEE方案使用的另外一個重要
方向,大疆無人機已經使用TEE方案來保護無人機
用戶的私人數據、航拍數據以及關鍵的飛控算法。
ARM的M系列也開始支持TrustZone技術,如何針
對資源受限的IoT設備實現TEE也是未來TEE的重要
發(fā)展方向之一。
而在車載領域NXP芯片已經集成OP-TEE作為
TEE方案,MediaTek的車載芯片也已集成了
Trustonic的TEE方案,相信在車載系統(tǒng)領域TEE也
將漸漸普及。1.4 為什么選擇OP-TEE
本書主要是介紹OP-TEE的實現原理,OP-TEE
是由非營利的開源軟件工程公司Linaro開發(fā)的,從
git上可以獲取OP-TEE的所有源代碼,且OP-TEE支
持的芯片也越來越多,相信未來OP-TEE將有可能
是TEE領域的Linux,并得到更加廣泛的運用。
OP-TEE是按照GP規(guī)范開發(fā)的,支持QEMU、Hikey(Linaro推廣的96Board系列平臺之一,使用
Hisilicon處理器)以及其他通用的ARMv7ARMv8
平臺,開發(fā)環(huán)境搭建方便,便于開發(fā)者開發(fā)自有的
上層可信應用,且OP-TEE提供了完整的軟件開發(fā)
工具包(Software Development Kit,SDK),方便
編譯TA和CA。OP-TEE遵循GP規(guī)范,支持各種加
解密和電子簽名驗簽算法以便實現DRM、在線支
付、指紋和虹膜識別功能。OP-TEE也支持在芯片
中集成第三方的硬件加解密算法。除此之外,在
IoT和車載芯片領域也大都使用OP-TEE作為TEE解
決方案。
OP-TEE由Linaro組織負責維護,安全漏洞補丁
更新和代碼迭代速度較快,系統(tǒng)的健壯性也越來越
好,所以利用OP-TEE來研究TrustZone技術的實現
并開發(fā)TA和CA將會是一個很好的選擇。本書涉及的內核源代碼使用的是OP-TEE 2.4版
本,書中所有的示例都在最新版本中測試通過。第2章 ARM的TrustZone技術
2.1 TrustZone技術
為提高系統(tǒng)的安全性,ARM早在ARMv6架構
中就引入了TrustZone技術[1]
,且在ARMv7和
ARMv8中得到增強,TrustZone技術能提供芯片級
別對硬件資源的保護和隔離,當前在手機芯片領域
已被廣泛應用。
[1] TrustZone硬件需求文檔:lcu14-
500armtrustedfirmware-140919105449-
phpapp02.pdf;TrustZone白皮書:PRD29-GENC-
009492C_TrustZone_security_whitepaper.pdf。2.1.1 片上系統(tǒng)硬件框架
一個完整的片上系統(tǒng)(System on Chip,SoC)
由ARM核、系統(tǒng)總線、片上RAM、片上ROM以及
其他外圍設備組件構成。只有支持TrustZone技術的
ARM核配合安全擴展組件,才能為整個系統(tǒng)提供芯
片硬件級別的保護和隔離。如圖2-1所示是一個支
持TrustZone的SoC的硬件框圖。
支持TrustZone技術的ARM核在運行時將工作
狀態(tài)劃分為兩種:安全狀態(tài)和非安全狀態(tài)。當處理
器核處于安全狀態(tài)時只能運行TEE側的代碼,且具
有REE側地址空間的訪問權限。當處理器核處于非
安全狀態(tài)時只能運行REE側的代碼,且只能通過事
先定義好的客戶端接口來獲取TEE側中特定的數據
和調用特定的功能。
系統(tǒng)通過調用安全監(jiān)控模式調用(secure
monitor call,smc)指令實現ARM核的安全狀態(tài)與
非安全狀態(tài)之間的切換。而ARM核對系統(tǒng)資源的訪
問請求是否合法,則由SoC上的安全組件通過判定
ARM核發(fā)送到SoC系統(tǒng)總線上的訪問請求中的安全
狀態(tài)讀寫信號位(Non-secure bit,NS bit)來決
定。只有當ARM核處于安全狀態(tài)(NS bit=0)時發(fā)
送到系統(tǒng)總線上的讀寫操作才會被識別為安全讀寫操作,對應TEE側的數據資源才能被訪問。反之,當ARM核處于非安全狀態(tài)(NS bit=1)時,ARM核
發(fā)送到系統(tǒng)總線上的讀寫操作請求會被作為非安全
讀寫操作,安全組件會根據對資源的訪問權限配置
來決定是否響應該訪問請求。這也是TrustZone技術
能實現對系統(tǒng)資源硬件級別的保護和隔離的根本原
因。
圖2-1 SoC硬件框2.1.2 ARMv7架構的TrustZone技術
ARMv7架構中使用了TrustZone技術的系統(tǒng)軟
件層面的框圖如圖2-2所示。
圖2-2 ARMv7系統(tǒng)軟件框架
在ARMv7架構中CPU在運行時具有不同的特權
等級,分別是PL0(USR)、PL1(FIQIRQ、SYS、ABT、SVC、UND和MON)以及
PL2(Hyp),即ARMv7架構在原有七種模式之上
擴展出了Monitor模式和Hyp模式。Hyp模式是ARM
核用于實現虛擬化技術的一種模式。系統(tǒng)只有在
Monitor模式下才能實現安全狀態(tài)和非安全狀態(tài)的切
換。當系統(tǒng)在REE側或者TEE側運行時,系統(tǒng)執(zhí)行
smc(安全監(jiān)控模式調用)指令進入Monitor模式,通過判定系統(tǒng)SCR寄存器中對應的值來確定請求來
源(REETEE)以及發(fā)送目標(REETEE),相關
寄存器中的值只有當系統(tǒng)處于安全態(tài)時才可以更
改,關于安全狀態(tài)與非安全狀態(tài)之間的切換過程,在本書第10章中將進行詳細介紹。2.1.3 ARMv8架構的TrustZone技術
在ARMv8架構中改用執(zhí)行等級(Execution
Level,EL)EL0~EL3來定義ARM核的運行等級,其中EL0~EL2等級分為安全態(tài)和非安全態(tài)。
ARMv8架構與ARMv7架構中ARM核運行權限的對
應關系如圖2-3所示。
圖2-3 ARMv7v8運行權限對比
ARMv7和ARMv8架構下特權等級和工作模式
的對應關系分別如表2-1所示。
表2-1 ARMv7和ARMv8架構下各模式對應關系ARMv7架構中的PL0(USR)對應ARMv8架構
中的EL0,PL1(SVCABTIRQFIQUNDSYS)對
應ARMv8架構中的EL1,ARMv7架構中的Hyp模式
對應ARMv8架構中的EL2,而ARMv7架構中的
Mon(Monitor)則對應于ARMv8架構中的EL3。
ARMv8架構同樣也是使用安全監(jiān)控模式調用
指令使處理器進入EL3,在EL3中運行的代碼負責
處理器安全狀態(tài)和非安全狀態(tài)的切換,其中關于
TEE和REE切換的處理方式與ARMv7架構中Monitor
模式下的處理方式類似,本書第10章將結合實際代
碼進行詳細分析。2.2 ARM安全擴展組件
TrustZone技術之所以能提高系統(tǒng)的安全性,是
因為對外部資源和內存資源的硬件隔離。這些硬件
隔離包括中斷隔離、片上RAM和ROM的隔離、片
外RAM和ROM的隔離、外圍設備的硬件隔離、外
部RAM和ROM的隔離等。實現硬件層面的各種隔
離,需要對整個系統(tǒng)的硬件和處理器核做出相應的
擴展。這些擴展包括:
·對處理器核的虛擬化,也就是將AMR處理器
的運行狀態(tài)分為安全態(tài)和非安全態(tài)。
·對總線的擴展,增加安全位讀寫信號線。
·對內存管理單元(Memory Management
Unit,MMU)的擴展,增加頁表的安全位。
·對緩存(Cache)的擴展,增加安全位。
·對其他外圍組件進行了相應的擴展,提供安
全操作權限控制和安全操作信號。2.2.1 AXI總線上安全狀態(tài)位的擴展
為了支持TrustZone技術,控制處理器在不同狀
態(tài)下對硬件資源訪問的權限,ARM對先進可擴展接
口(Advanced eXtensible Interface,AXI)系統(tǒng)總線
進行了擴展。在原有AXI總線基礎上對每一個讀寫
信道增加了一個額外的控制信號位,用來表示當前
的讀寫操作是安全操作還是非安全操作,該信號位
稱為安全狀態(tài)位(NS bit)或者非安全狀態(tài)位
(Non-Secure bit)。
·AWPROT[1]:總線寫事務——低位表示安全
寫事務操作,高位表示非安全寫事務操作。
·ARPROT[1]:總線讀事務——低位表示安全
讀事務操作,高位表示非安全讀事務操作。
當主設備通過總線發(fā)起讀寫操作時,從設備或
者外圍資源同時也需要將對應的PROT控制信號發(fā)
送到總線上。總線或者從設備的解碼邏輯必須能夠
解析該PROT控制信號,以便保證安全設備在非安
全態(tài)下不被非法訪問。所有的非安全主設備必須將
安全狀態(tài)位置成高位,這樣就能夠保證非安全主設
備無法訪問到安全從設備。如果一個非安全主設備
試圖訪問一個安全從設備,將會在總線或者從設備上觸發(fā)一個錯誤操作,至于該錯誤如何處理就依賴
于從設備的處理邏輯和總線的配置。通常這種非法
操作最終將產生一個SLVERR(slave error)或者
DECERR(decode error)。2.2.2 AXI-to-APB橋的作用
TrustZone同樣能夠保護外圍設備的安全,例如
中斷控制、時鐘、IO設備,因此Trust-Zone架構還
能用來解決更加廣泛的安全問題。比如一個安全中
斷控制器和安全時鐘允許一個非中斷的安全任務來
監(jiān)控系統(tǒng),能夠為DRM提供可靠的時鐘,能夠為用
戶提供一個安全的輸入設備從而保證用戶密碼數據
不會被惡意軟件竊取。
AMBA3規(guī)范包含了一個低門數、低帶寬的外
設總線,被稱作外設總線(Advanced Peripheral
Bus,APB),APB通過AXI-to-APB橋連接到系統(tǒng)
總線上。而APB總線并不具有安全狀態(tài)位,為實現
APB外設與TrustZone技術相兼容,APB-to-AXI橋將
負責管理APB總線上設備的安全。APB-to-AXI橋會
拒絕不匹配的安全事務設置,并且不會將該事務請
求發(fā)送給外設。2.2.3 TrustZone地址空間控制組件
TrustZone地址空間控制組件(TrustZone
Address Space Controller,TZASC)[1]
是AXI總線上
的一個主設備,TZASC能夠將從設備全部的地址空
間分割成一系列的不同地址范圍。在安全狀態(tài)下,通過編程TZASC能夠將這一系列分割后的地址區(qū)域
設定成安全空間或者是非安全空間。被配置成安全
屬性的區(qū)域將會拒絕非安全的訪問請求。
使用TZASC主要是將一個AXI從設備分割成幾
個安全設備,例如off-Soc、DRAM等。ARM的動態(tài)
內存控制器(Dynamic Memory Controller,DMC)
并不支持安全和非安全分區(qū)的功能。如果將DMC接
到TZASC上,就能實現DRAM支持安全區(qū)域和非安
全區(qū)域訪問的功能。需要注意的是,TZASC組件只
支持存儲映射設備對安全和非安全區(qū)域的劃分與擴
展,但不支持對塊設備(如EMMC、NAND flash
等)的安全和非安全區(qū)域的劃分與擴展。圖2-4所
示為使用TZASC組件的例子。圖2-4 TZASC組件示意
[1] TZASC文檔:
DDI0431C_tzasc_tzc380_r0p1_trm.pdf。2.2.4 TrustZone內存適配器組件
TrustZone內存適配器組件(TrustZone Memory
Adapter,TZMA)[1]
允許對片上靜態(tài)內存(on-SoC
Static Memory)或者片上ROM進行安全區(qū)域和非安
全區(qū)域的劃分。TZMA支持最大2MB空間的片上靜
態(tài)RAM的劃分,可以將2MB空間劃分成兩個部
分,高地址部分為非安全區(qū)域,低地址部分為安全
區(qū)域,兩個區(qū)域必須按照4KB進行對齊。分區(qū)的具
體大小通過TZMA的輸入信號R0SIZE來控制,該信
號來自TZPC的輸出信號TZPCR0SIZE。即通過編程
TZPC可以動態(tài)地配置片上靜態(tài)RAM或者ROM的大
小。使用TZMA組件的鏈接框圖如圖2-5所示。
圖2-5 使用TZMA組件的鏈接示意
[1] TZMA文檔:
cycle_models_BP141_TZMA_User_Guide_v9_1_0_DUI1083A_en.pdf。2.2.5 TrustZone保護控制器組件
TrustZone保護控制器組件(TrustZone
Protection Controller,TZPC)[1]
是用來設定
TZPCDECPORT信號和TZPCR0SIZE等相關控制信
號的。這些信號用來告知APB-to-AXI對應的外設是
安全設備還是非安全設備,而TZPCR0SIZE信號用
來控制TZMA對片上RAM或片上ROM安全區(qū)域大
小的劃分。TZPC包含三組通用寄存器
TZPCDECPROT[2:0],每組通用寄存器可以產生8
種TZPCDECPROT信號,也就是TZPC最多可以將
24個外設設定成安全外設。TZPC組件還包含一個
TZPCROSIZE寄存器,該寄存器用來為TZMA提供
分區(qū)大小信息。TZPC組件的接口示意如圖2-6所
示。
當上電初始化時,TZPC的TZPCDECROT寄存
器中的位會被清零,同時TZPCR0SIZE寄存器會被
設置成0x200,表示接入到TZMA上的片上RAM或
者ROM的安全區(qū)域大小為2MB。通過修改TZPC的
寄存器配置的值可實現用戶對資源的特定配置。
TZPC的使用例子如圖2-7所示。圖2-6 TZPC組件接口示意
圖2-7 TZPC使用示例
[1] TZPC文檔(BP147):
DTO0015_primecell_infrastructure_amba3_tzpc_bp147_to.pdf。2.2.6 TrustZone中斷控制器組件
在支持TrustZone的SoC上,ARM添加了
TrustZone中斷控制器(TrustZone Interrupt
Controller,TZIC)[1]。TZIC的作用是讓處理器處
于非安全態(tài)時無法捕獲到安全中斷。TZIC是第一級
中斷控制器,所有的中斷源都需要接到TZIC上。
TZIC根據配置來判定產生的中斷類型,然后決定是
將該中斷信號先發(fā)送到非安全的向量中斷控制器
(Vector Interrupt Controller,VIC)后以nIRQ信號
發(fā)送到處理器,還是以nTZICFIQ信號直接發(fā)送到
處理器。圖2-8所示為TZIC在SoC中的使用示意。
圖2-8 TZIC在SoC中的使用示意
通過對TZIC的相關寄存器進行編程,可對
TZIC進行配置并設定每個接入到TZIC的中斷源的中斷類型。TZIC具有眾多寄存器,細節(jié)說明可以參
考相關ARM的文檔。在TZIC中用來設置中斷源類
型的寄存器為TZICIntSelect,如果TZICIntSelect中
的某一位被設置成1,則該相應的中斷源請求會被
設置成快速中斷請求(Fast Interrupt Request,FIQ)。如果某一位被設置成0,則該中斷源的中斷
請求會被交給VIC進行處理。如果VIC的IntSelect將
獲取到的中斷源設置成FIQ,那么該中斷源會被再
次反饋給TZIC進行處理。
[1] TZIC文檔:
DTO0013B_tzic_sp890_r0p0_to.pdf。2.2.7 Cache和MMU的擴展
在支持TrustZone的SoC上,會對MMU進行虛
擬化,使得寄存器TTBR0、TTBR1、TTBCR在安
全狀態(tài)和非安全狀態(tài)下是相互隔離的,因此兩種狀
態(tài)下的虛擬地址轉換表是獨立的。
存放在MMU中的每一條頁表描述符都會包含
一個安全狀態(tài)位,用以表示被映射的內存是屬于安
全內存還是非安全內存。虛擬化的MMU共享轉換
監(jiān)測緩沖區(qū)(Translation Lookaside Buffer,TLB),同樣TLB中的每一項也會打上安全狀態(tài)位
標記,只不過該標記是用來表示該條轉換是正常世
界狀態(tài)轉化的還是安全世界狀態(tài)轉化的。
Cache也同樣進行了擴展,Cache中的每一項都
會按照安全狀態(tài)和非安全狀態(tài)打上對應的標簽,在
不同的狀態(tài)下,處理器只能使用對應狀態(tài)下的
Cache。2.3 TrustZone技術對資源隔離的實現
ARM處理器核的虛擬化和資源隔離是
TrustZone實現安全需求的根本。支持TrustZone的
處理器核具有虛擬化,也即將一個物理核分成安全
狀態(tài)和非安全狀態(tài)。當處理器處于非安全狀態(tài)時,只能訪問屬于非安全的外設和內存,而不能訪問安
全的資源;當處理器處于安全態(tài)時,處理器既可以
訪問安全資源,也可以訪問非安全的資源,只有當
處理器核為安全世界狀態(tài)時才可能發(fā)出PROT的安
全訪問信號。2.3.1 中斷源的隔離
在原來的ARM芯片中,使用VIC來對外部中斷
源進行控制和管理,支持TrustZone后,ARM提出
了TZIC組件,在芯片設計時,該組件作為一級中斷
源控制器,控制所有的外部中斷源,通過編程TZIC
組件的相關寄存器來設定哪個中斷源為安全中斷源
FIQ,而未被設定的中斷源將會被傳遞給VIC進行
處理。一般情況下VIC會將接收到的中斷源設定成
普通中斷請求(Interrupt Request,IRQ),如果在
VIC中將接收到的中斷源設定成FIQ,則該中斷源
會被反饋給TZIC組件,TZIC組件會將安全中斷源
送到安全世界狀態(tài)中進行處理。2.3.2 片上RAM和片上ROM的隔離
芯片內部存在小容量的RAM或者ROM,以供
芯片上電時運行芯片ROM或者存放芯片自身相關的
數據。TrustZone架構對該部分也進行了隔離操作。
隔離操作通過使用TZMA和TZPC組件來實現。
TZMA用來將片上RAM或者ROM劃分成安全
區(qū)域和非安全區(qū)域,安全區(qū)域的大小則由接入的
TZPCR0SIZE信號來決定。而TZPCR0SIZE的值可
以通過編程TZPC組件中的TZPCR0SIZE寄存器來實
現。
當處理器核訪問片上RAM或者ROM時,TZMA會判定訪問請求的PROT信號是安全操作還
是非安全操作,如果處理器發(fā)出的請求為非安全請
求而該請求又嘗試去訪問安全區(qū)域時,TZMA就會
認為該請求為非法請求。這樣就能實現片上RAM和
ROM的隔離,達到非安全態(tài)的處理器核無法訪問片
上安全區(qū)域的RAM和ROM。2.3.3 片外DRAM的隔離
一個完整的系統(tǒng)必然會有片外RAM,對片外
RAM的隔離是通過TZASC組件實現的,ARM本身
的DMC可以將DRAM分割成不同的區(qū)域,這些區(qū)域
是沒有安全和非安全分類。將DMC與TZASC相連
后再掛到總線上,通過對TZASC組件進行編程可以
將DRAM劃分成安全區(qū)域和非安全區(qū)域。當主設備
訪問DRAM時,除需要提供物理地址之外,還會發(fā)
送PROT信號。TZASC組件首先會判定主設備需要
訪問的DARM地址是屬于安全區(qū)域還是非安全區(qū)
域,然后再結合接收到的PROT信號來判定該次訪
問是否有效。如果PROT信號為非安全訪問操作,且訪問的DRAM地址屬于安全區(qū)域,則TZASC就不
會響應這次訪問操作,這樣就能實現DRAM中安全
區(qū)域和非安全區(qū)域的隔離。2.3.4 外圍設備的隔離
其他外圍設備都會掛載到APB總線上,然后通
過AXI-to-APB橋連接到AXI總線上,AXI-to-APB結
合TZPC組件的TZPCDECROT的值及訪問請求的
PROT信號來判定該訪問是否有效。當處理器需要
訪問外圍設備時,會將地址和PROT信號發(fā)送到
AXI總線上。
AXI-to-APB橋會對接收到的請求進行解析,獲
取需要訪問的所需外圍設備,然后通過查詢
TZPCDECROT的值來判斷外設的安全類型,再根
據PROT信號就能判定該請求的安全類型。如果該
請求是非安全請求,但需要訪問的外圍設備屬于安
全設備,則AXI-to-APB會判定該訪問無效。
通過對TZPC中的TZPCDECROT寄存器進行編
程能夠設置外設的安全類型,從而做到外設在硬件
層面的隔離。2.4 小結
本章介紹了TrustZone的原理以及在ARMv7和
ARMv8架構下TrustZone技術實現的差異。
TrustZone對系統(tǒng)實現了硬件隔離,將系統(tǒng)資源劃分
成安全和非安全兩種類型,同時在系統(tǒng)總線上增加
安全讀寫信號位,通過讀取安全讀寫信號位電平來
確定當前處理器的工作狀態(tài),從而判斷是否具有該
資源的訪問權限。因此,TrustZone從硬件級別實現
了對系統(tǒng)資源的保護。第3章 ARM可信固件
3.1 為什么使用ATF
ARM可信任固件(ARM Trusted Firmware,ATF)是由ARM官方提供的底層固件,該固件統(tǒng)一
了ARM底層接口標準,如電源狀態(tài)控制接口
(Power Status Control Interface,PSCI)、安全啟
動需求(Trusted Board Boot Requirements,TBBR)、安全世界狀態(tài)(SWS)與正常世界狀態(tài)
(NWS)切換的安全監(jiān)控模式調用(secure monitor
call,smc)操作等。ATF旨在將ARM底層的操作統(tǒng)
一使代碼能夠重用和便于移植。3.2 ATF的主要功能
ATF的源代碼共分為bl1、bl2、bl31、bl32、bl33部分,其中bl1、bl2、bl31部分屬于固定的固
件,bl32和bl33分別用于加載TEE OS和REE側的鏡
像。整個加載過程可配置成安全啟動的方式,每一
個鏡像文件在被加載之前都會驗證鏡像文件的電子
簽名是否合法。
ATF主要完成的功能如下:
·初始化安全世界狀態(tài)運行環(huán)境、異常向量、控制寄存器、中斷控制器、配置平臺的中斷。
·初始化ARM通用中斷控制器(General
Interrupt Controller,GIC)2.0版本和3.0版本的驅動
初始化。
·執(zhí)行ARM系統(tǒng)IP的標準初始化操作以及安全
擴展組件的基本配置。
·安全監(jiān)控模式調用(Secure Monitor Call,smc)請求的邏輯處理代碼(Monitor模式EL3)。
·實現可信板級引導功能,對引導過程中加載的鏡像文件進行電子簽名檢查。
·支持自有固件的引導,開發(fā)者可根據具體需
求將自有固件添加到ATF的引導流程中。3.3 ATF與TEE的關系
為規(guī)范和簡化TrustZone OS的集成,在ARMv8
架構中,ARM引入ATF作為底層固件并開放了源
碼,用于完成系統(tǒng)中BootLoader、Linux內核、TEE
OS的加載和啟動以及正常世界狀態(tài)和安全世界狀態(tài)
的切換。ATF將整個啟動過程劃分成不同的啟動階
段,由BLx來表示。例如,TEE OS的加載是由ATF
中的bl32來完成的,安全世界狀態(tài)和正常世界狀態(tài)
之間的切換是由bl31來完成的。在加載完TEE OS之
后,TEE OS需要返回一個處理函數的接口結構體
變量給bl31。當在REE側觸發(fā)安全監(jiān)控模式調用指
令時,bl31通過查詢該結構體變量就可知需要將安
全監(jiān)控模式調用指令請求發(fā)送給TEE中的那個接口
并完成正常世界狀態(tài)到安全世界狀態(tài)的切換。3.4 小結
在ARMv8架構中,如果系統(tǒng)需要支持TEE,則
幾乎都必須使用由ARM提供的ATF作為底層固件。
關于ATF如何管理BootLoader、TEE OS、Linux內
核以及各個階段鏡像的加載過程和跳轉過程,本書
第6章將結合實際代碼詳細分析。第4章 OP-TEE運行環(huán)境的搭建及編
譯
OP-TEE是開源的TEE解決方案,任何人都可
從github庫中獲取OP-TEE的源代碼,本章主要包括
如何從github中獲取OP-TEE的源代碼、如何搭建運
行環(huán)境以及整個OP-TEE工程的編譯過程。本書以
QEMU作為運行平臺,Hikey或者其他平臺的編譯
和使用方式與QEMU平臺類似。4.1 獲取OP-TEE代碼并搭建運行環(huán)境
OP-TEE的開發(fā)環(huán)境推薦使用Linux進行搭建,可在Windows系統(tǒng)中使用虛擬機創(chuàng)建一個Ubuntu系
統(tǒng)或者將計算機系統(tǒng)換成Ubuntu系統(tǒng)。4.1.1 OP-TEE開發(fā)環(huán)境的搭建
OP-TEE的開發(fā)環(huán)境依賴于各種基本庫,在
Ubuntu系統(tǒng)中直接運行如下指令就可安裝OP-TEE
開發(fā)環(huán)境需要使用的各種依賴庫。
sudo apt-get install android-tools-adb android-tools-fastboot autoconf automake bc bison build-essential cscope curl device-tree-compiler expect flex ftp-upload gdisk iasl libattr1-dev libc6:i386 libcap-dev libfdt-dev libftdi-dev libglib2.0-dev libhidapi-dev libncurses5-dev libpixman-1-dev libssl-dev libstdc++6:i386 libtool libz1:i386 make mtools netcat python-crypto python-serial python-wand unzip uuid-dev xdg-utils xterm xz-utils zlib1g-dev4.1.2 獲取OP-TEE的源代碼
在系統(tǒng)中創(chuàng)建用于存放OP-TEE的目錄“open-
tee”,讀者可以根據自己的喜好替換目錄的名字,創(chuàng)建完目錄后就需要建立OP-TEE的repo(關于repo
或者git的使用,請讀者自行查找資料了解),初始
化完repo后,使用repo sync指令就可從Github上獲
取到OP-TEE的源代碼,操作如下:
mkdir open-tee 創(chuàng)建目錄
cd open-tee 切換到創(chuàng)建的目錄
repo init -u https: github.comOP-TEEmanifest.git -m default.xml --repo-url=git:codeaurora.orgtoolsrepo.git -b 2.6.0 初始化repo
repo sync 開始獲取OP-TEE源代碼
如果在執(zhí)行repo sync時出現“remote:
Repository not found”的報錯提示,則需要修改open-
tee.repo目錄下的manifest.xml文件,將該文件中所
有project域中的“.git”刪除,也可通過如下指令進行
修改:
sed -i s\.gitg .repomanifest.xml
修改完成之后,重新執(zhí)行repo sync來獲取OP-
TEE的代碼。manifest.xml文件中包含的就是整個工
程所需的單獨git倉庫的鏈接[1]。待代碼同步完成后,為方便后續(xù)章節(jié)中各示例
代碼的集成,需要使用如下指令將相關的代碼回滾
到標簽為3.0.0的版本。
cd optee_client
git checkout 3.0.0
cd optee_test
git checkout 3.0.0
cd optee_benchmark
git checkout 3.0.0
cd optee_examples
git checkout 3.0.0
cd optee_os
git checkout 3.0.0
[1] OP-TEE工程源代碼鏈接:https:github.comOP-
TEE;OP-TEE內核代碼鏈接:
https:github.comOP-TEEoptee_os;OP-TEE client
端代碼鏈接:https:github.comOP-
TEEoptee_client;OP-TEE test代碼鏈接:
https:github.comOP-TEEoptee_test;OP-TEE工程
使用的Linux Kernel代碼鏈接:
https:github.comlinaroswglinux;OP-TEE 中使用
的QEMU 軟件源代碼鏈接:
https:github.comlinaro-swgqemu。4.1.3 獲取編譯OP-TEE的toolchain
OP-TEE工程的源代碼下載完成后,下一步就
需要獲取編譯OP-TEE時使用的toolchain,切換到源
代碼的build目錄,執(zhí)行如下指令:
cd build 切換到build目錄
make -f toolchain.mk toolchains 下載toolchain
查看toolchain.mk文件可知,執(zhí)行make指令之
后,系統(tǒng)會去下載toolchains的tar包,包括32位和64
位的編譯鏈接工具,下載完成后會進行解壓操作。
執(zhí)行完make后,可發(fā)現OP-TEE源代碼的根目錄下
會多出一個toolchains的目錄,該目錄中存放的就是
編譯OP-TEE工程時使用的所有編譯鏈接工具。4.1.4 編譯QEMU
OP-TEE源代碼的build目錄是用于編譯整個工
程的編譯目錄,該目錄包含各種平臺的編譯配置文
件。在QEMU平臺運行時需選擇qemu.mk文件進行
編譯,具體操作如下:
cd build 切換到build目錄
make -f qemu.mk all 編譯工程
當然,讀者也可將qemu.mk文件鏈接成
Makefile,然后在build目錄下直接執(zhí)行make all就能
編譯QEMU平臺的工程。
編譯完成后將會在OP-TEE的根目錄下生成一
個out目錄,該目錄中存放的就是使用QEMU方式運
行OP-TEE時需要的鏡像和其他相關文件。
如果在編譯的過程中出現“ImportError:No
Module named wand.image”的報錯提示,說明系統(tǒng)
沒有安裝Python的Wand包,此時在shell中運行如下
指令即可:
pip install: Wand4.1.5 運行OP-TEE
工程編譯完成之后,如果要運行OP-TEE,則
需要進入build目錄中執(zhí)行make run-only語句,具體
操作如下:
cd build 切換到build目錄
make -f qemu.mk run-only 啟動QEMU并運行OP-TEE
如果讀者已將qemu.mk文件鏈接成了
Makefile,則直接在build目錄中執(zhí)行make run-only
即可。qemu.mk文件中的run-only目標首先會啟動兩
個分別屬于安全世界狀態(tài)和正常世界狀態(tài)的
terminal,用于顯示OP-TEE和Linux內核的日志數
據,然后加載OP-TEE鏡像與Linux的鏡像及其文件
系統(tǒng)。4.1.6 運行xtest和optee_example_hello_world
通過使用make run-only啟動OP-TEE后,可在
啟動的正常世界狀態(tài)對應的terminal中執(zhí)行
Optee_example_hello_world或者xtest指令來檢查OP-
TEE是否正常運行。
Optee_example_hello_world是一個簡單的CA編
譯而成的二進制可執(zhí)行文件,執(zhí)行該可執(zhí)行文件后
會調用OP-TEE中對應的TA,并執(zhí)行一些簡單的打
印操作,輸出的日志信息可在安全世界狀態(tài)的
terminal中查看。
xtest是OP-TEE自帶的一個測試使用的CA可執(zhí)
行文件。該CA執(zhí)行后將會調用TA中的各種功能,包括檢查基本算法接口、安全存儲接口等。4.2 運行CA和TA示例
OP-TEE中自帶的TA和CA都保存在
optee_examples目錄中,那么如何添加自己開發(fā)的
TA和CA程序到OP-TEE中并運行呢?本節(jié)將對此進
行介紹。為減少對編譯方面的理解,本節(jié)將結合實
際的TA和CA示例介紹詳細的操作步驟。4.2.1 示例代碼的獲取和集成
本節(jié)所用示例的所有源代碼可從gitHub上獲
取,讀者可使用如下指令獲取到源代碼,示例包中
有對應的補丁,讀者直接合入補丁就可將該示例集
成到OP-TEE中,該示例的gitHub鏈接如下:
git clone https:github.comshuaifengyunoptee_my_test.git
獲取到示例代碼之后,切換到如下build目錄
下,然后使用git apply命令合入補丁文件后就可將
該示例集成到OP-TEE,合入補丁的操作步驟如
下:
1)將示例代碼中的
optee_mytest_common_3.0.0.patch文件和
optee_mytest_qemu_3.0.0.patch文件復制到build目錄
中。
2)切換到build目錄,使用如下命令合入補
。
git apply optee_mytest_common_3.0.0.patch
git apply optee_mytest_qemu_3.0.0.patch將補丁合入之后就可使用make-f qemu.mk all編
譯整個工程,然后使用make-f qemu.mk run-only來
啟動OP-TEE,在啟動的正常世界狀態(tài)的終端執(zhí)行
my_test命令就能實現該示例的CA對TA的調用。示
例代碼的運行效果如圖4-1所示。
圖4-1 optee_my_test示例運行4.2.2 目錄和文件創(chuàng)建
從gitHub上獲取到本章使用的示例代碼后,host存放的是CA的代碼,ta目錄存放的是TA部分的
代碼。本章提供的示例代碼的目錄結構如下:
├── Android.mk
├── build_ta_mytest_qemu.sh
├── doc
│ ├── close_session_and_finalize_context.msc
│ ├── invoke_command.msc
│ ├── Makefile
│ └── open_session.msc
├── host
│ ├── main.c
│ ├── Makefile
│ └── my_test_ca.h
├── Makefile
├── optee_mytest_common_3.0.0.patch
├── optee_mytest_qemu_3.0.0.patch
├── README.md
└── ta
├── Android.mk
├── include
│ ├── my_test_handle.h
│ └── my_test_ta.h
├── Makefile
├── my_test.c
├── my_test_handle.c
├── sub.mk
└── user_ta_header_defines.h
目錄中文件的作用說明如下:·Android.mk文件:Android系統(tǒng)中編譯整個TA
和CA時使用;
·build_ta_mytest_qemu.sh文件:單獨編譯TA和
CA使用的腳本文件;
·hostmain.c文件:CA的源代碼;
·hostMakefile文件:編譯CA時使用的makefile
文件;
·hostmy_test_ca.h文件:UUID、command ID
的宏定義;
·taMakefile文件:編譯TA時使用的makefile文
件;
·tamy_test.c文件:主要是存放TA部分代碼的
入口處理函數,CA的command請求最終會被
TA_InvokeCommandEntryPoint函數處理;
·tamy_test_handle.c文件:存放相應CA的
command請求的功能函數;
·tasub.mk文件:定義該TA中需要被編譯的
source code;·tauser_ta_header_defines.h文件:定義UUID等
相關宏;
·taincludemy_test_handle.h文件:定義了該TA
需要使用的類型;
·taincludemy_test_ta.h文件:定義了UUID的宏
以及與CA對應的command ID宏;
·optee_mytest_common_3.0.0.patch文件:將該
TA和CA集成到OP-TEE時buildcommon.mk文件使
用的補丁文件;
·optee_mytest_qemu_3.0.0.patch文件:將該TA
和CA集成到OP-TEE時builldqemu.mk文件使用的補
丁文件。4.2.3 CA端代碼的修改
若讀者需添加新的功能,可按照GP規(guī)范調用
REE側的相關接口,編輯完CA端的代碼后就需要修
改host目錄下的Makefile文件,將需要編譯進CA的
文件添加到Makefile中,主要是修改hostMakefile文
件中的OBJS變量和BINARY變量,其中OBJS變量
存放的是需要編譯到CA的目標文件或者庫文件,BINARY是編譯完成后的可執(zhí)行文件的名字。注
意,在CA的頭文件中需要定義UUID和command ID
的宏,且定義的內容需要與TA中的UUID和
command ID一致,否則執(zhí)行CA后將會導致調用失
敗,關于UUID的值并沒有特殊的要求,只需按照
其格式定義一個唯一的字符串即可。4.2.4 TA端代碼的修改
ta目錄中存放的是該TA的源代碼、makefile文
件和頭文件,其中ta目錄中必須存在一個
user_ta_header.h文件,該文件在編譯TA鏡像或者是
整個工程時會被使用到。在該文件中會定義UUID
的宏、該TA運行的堆?臻g的大小以及版本信
息。在TA的頭文件中需要定義UUID的宏和
command ID,且必須與CA中定義的一樣,否則CA
端將無法調用該TA中對應的操作。修改taMakefile
文件,將該文件中BINARY變量的值修改成與CA中
相同的UUID值。
修改完成后運行build_ta_mytest_qemu.sh腳本
就能單獨編譯CA和TA,如果出現錯誤,則根據提
示進行修改,編譯成功后會在ta目錄中生成與UUID
值一樣的elf文件,在host目錄中將會生成與
hostMakefile文件中BINARY變量的值一樣的文
件。4.2.5 TA和CA在OP-TEE的集成
單獨編譯TA和CA成功后,就需要將該TA和
CA集成到OP-TEE的工程中去,需要修改OP-TEE源
代碼中build目錄下的qemu.mk文件和common.mk文
件。
在buildqemu.mk文件中增加該TA的目標和依
賴關系,以本示例為例,對buildqemu.mk文件的修
改如下。
1)增加optee_my_test的編譯目標內容:
optee_my_test
Optee_mytest: optee_mytest-common
Optee_mytest-clean: optee_mytest-clean-common
2)將optee_mytest目標和optee_mytest-clean-
common目標添加到all中:
all: bios-qemu qemu soc-term optee-examples optee_my_test
clean: bios-qemu-clean busybox-clean linux-clean optee-os-clean optee-client-clean qemu-clean soc-term-clean check-clean optee_my_test-clean optee-examples-clean在buildcommon.mk文件中需要增加編譯該TA
和CA的路徑變量等信息,添加的內容如下。
1)增加TA和CA的代碼路徑:
OPTEE_MYTEST_PATH ?= (ROOT)optee_my_test
2)增加TA和CA的common目標:
optee_my_test
OPTEE_MYTEST_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: optee_my_test-common
optee_my_test-common: optee-os optee-client
(MAKE) -C (OPTEE_MYTEST_PATH) (OPTEE_MYTEST_COMMON_FLAGS)
OPTEE_MYTEST_CLEAN_COMMON_FLAGS ?= TA_DEV_KIT_DIR=(OPTEE_OS_TA_DEV_KIT_DIR)
.PHONY: optee_my_test-clean-common
optee_my_test-clean-common:
(MAKE) -C (OPTEE_MYTEST_PATH) (OPTEE_MYTEST_CLEAN_COMMON_FLAGS) clean
3)將該TA和CA添加到filelist-tee-common目標
的依賴關系中:
filelist-tee-common: optee-client xtest optee-examples optee_my_test
4)添加clean操作的依賴關系:optee-os-clean-common: xtest-clean optee-examples-clean optee_my_test-clean
5)在filelist-tee-common中添加TA和CA鏡像需
要被打包到文件系統(tǒng)中的操作:
@echo optee_mytest >> (fl)
@if [ -e (OPTEE_MYTEST_PATH)hostmy_test ]; then echo file binmy_test (OPTEE_MYTEST_PATH)hostmy_test 755 0 0 >> (fl); echo file liboptee_armtz9269fadd-99d5-4afb-a1dc-ee3e9c61b04c.ta (OPTEE_MYTEST_PATH)ta9269fadd-99d5-4afb-a1dc-ee3e9c61b04c.ta 444 0 0 >> (fl); fi4.3 OP-TEE源代碼結構
OP-TEE的源代碼包含運行OP-TEE時需要的所
有軟件源代碼,OP-TEE工程編譯完成后,整個源
代碼的目錄結構如下:
├── basicAlg_use
├── bios_qemu_tz_arm
├── build
├── busybox
├── gen_rootfs
├── linux
├── optee_benchmark
├── optee_client
├── optee_examples
├── optee_my_test
├── optee_os
├── optee_test
├── out
├── qemu
├── secStor_test
├── soc_term
└── toolchains
OP-TEE各子目錄中的代碼功能說明如下。
(1)bios_qemu_tz_arm目錄
在QEMU平臺中運行tz_arm的BIOS代碼,啟動
的最初階段會被使用到,用來加載Linux內核鏡
像、OP-TEE OS鏡像、rootfs并啟動Linux內核和OP-TEE OS。
(2)build目錄
OP-TEE工程的編譯目錄,包含各種mk文件和
相關配置文件,其中common.mk文件是工程的通用
mk文件,不同的CPU架構有不同的mk與之相對
應,編譯工程時可使用make-f的方式指定編譯哪個
板級的OP-TEE。
(3)busybox目錄
busybox的源代碼,編譯生成制作rootfs所需要
的文件和目錄。
(4)gen_rootfs目錄
存放制作rootfs時使用的相關腳本和配置文
件。
(5)linux目錄
Linux內核代碼,在drivertee目錄下存放的是
OP-TEE在REE側的驅動,任何在Linux用戶空間調
用CA的接口都會經過OP-TEE的REE側驅動處理之
后再轉發(fā)到TEE側。(6)optee_benchmark目錄
OP-TEE運行的性能測試工具,只保存CA端的
代碼,TA部分的代碼保存在OP-TEE OS中,作為
靜態(tài)TA集成到OP-TEE OS中。
(7)optee_client目錄
包含CA程序調用的用戶空間的接口庫
(libteec)的源代碼。其中tee_supplicant目錄中的
代碼會被編譯成一個可執(zhí)行文件,該可執(zhí)行文件在
Linux啟動時作為守護進程常駐在系統(tǒng)中,該守護
進程的主要作用是響應和處理來自TEE側的RPC請
求,這些RPC請求包括:加載TA鏡像、對文件系統(tǒng)
的操作、對SQL的操作、對EMMC RPMB的操作、網絡通信的socket操作等。
(8)optee_examples目錄
示例代碼,目錄下包含OP-TEE提供的各種示
例的TA和CA的所有代碼,啟動后,在REE對應的
terminal中執(zhí)行optee_example_hello_world命令后,會調用optee_example_hello_world的TA的邏輯,TA
根據接收到的command ID在OP-TEE中執(zhí)行對應的
操作。
(9)optee_os目錄存放OP-TEE OS的源代碼和相關文檔,編譯完
成之后,該目錄將會生成OP-TEE的鏡像文件。
(10)optee_test目錄
opentee的測試程序xtest的源代碼,主要用來測
試OP-TEE中提供的各種算法的邏輯并提供其他測
試功能。
(11)out目錄
編譯結果的輸出目錄(該目錄編譯完成之后才
會生成)。
(12)qemu目錄
QEMU源代碼,如果編譯的是qemu.mk,編譯
時將會使用到該目錄。
(13)soc_term目錄
在使用QEMU運行OP-TEE時,gnome-terminal
命令會啟動終端,用于建立啟動的兩個terminal的
端口監(jiān)聽,方便OP-TEE OS的log和Linux的log分別
輸出到對應的terminal中。
(14)toolchains目錄編譯時需要使用的編譯工具鏈,在build目錄下
執(zhí)行make–f toolchai.mk toolchains后將會生成該目
錄。4.4 OP-TEE編譯
整個OP-TEE工程的編譯是一個龐大的過程,牽扯到目標的依賴關系,本節(jié)以qemu.mk板級為
例,分析使用QEMU方式運行OP-TEE時的全部編
譯過程和目標依賴關系。4.4.1 編譯目標的依賴關系
編譯OP-TEE工程時各主要目標的依賴關系如
下:
all
├── bios-qemu
│ ├── optee-os
│ │ └── optee-os-common
│ └── update_rootfs
│ └── update_rootfs-common
│ ├── busybox
│ │ └── busybox-common
│ │ └── linux
│ │ └── linux-common
│ │ └── linux-defconfig
│ └── filelist-tee
│ └── filelist-tee-common
│ ├── f1
│ │ └── filelist-tee.txt
│ ├── optee-client
│ │ ├── common
│ │ └── optee-client
│ └── xtest
│ │ ├── optee-client
│ │ └── xtest-common
│ │ └── optee-os
│ │ └──optee-os-common
│ └── optee-examples
│ └── build_socterm
│ └── helloworld-common
│ ├──optee-client
│ └──optee-os
├── benchmark-app
├── qemu
│ └── build_qemu
└── soc-term
│ └── build_socterm └── optee-examples
│ └── build_socterm
│ └── helloworld-common
│ ├──optee-client
│ └──optee-os
QEMU目標會切換到QEMU目錄,并獲取
QEMU的配置文件,然后執(zhí)行make命令來編譯
QEMU目標。
soc-term目標會編譯soc-term目錄,生成一個
soc-term的可執(zhí)行文件,用于啟動兩個terminal。
bios-qemu目標依賴于update_rootfs和optee-os,update_rootfs和optee-os編譯完成之后會調用
biosqemu-comm宏定義的指令,該宏會編譯
bios_qemu_tz_arm目錄,該目錄編譯完成之后,會
生成啟動時需要的bios鏡像。
optee-os-common目標將編譯optee_os目錄,該
目錄編譯完成后將會生成tee.bin及其他的lib庫文
件。
busybox目標將編譯linux目錄和busybox目錄,生成Linux內核鏡像文件和制作rootfs需要的相關文
件。
filelist-tee目標將生成tee功能相關的文件和需要被掛載到rootfs中的映射圖,然后與系統(tǒng)的其他文
件的掛載映射關系一起保存到filelist-final.txt文件
中,用于生成filesystem.cpio.gz文件。
update_rootfs-common目標依賴于busybox和
filelist-tee目標,上述兩個目標編譯完成之后,將會
切換到gen_rootfs目錄中,調用gen_init_cpio命令生
成在啟動時需要使用的filesystem.cpio.gz文件。
Optee_examples目標包含OP-TEE提供的各種
TA部分和CA部分,編譯完成之后,會生成對應的
TA鏡像文件和CA的可執(zhí)行文件。
optee-client目標將對optee_client目錄進行編
譯,生成一系列的庫文件和可執(zhí)行文件,庫文件提
供了OP-TEE在Linux端的接口,將被所有CA調用。
tee-supplicant目標將會編譯生成一個tee_supplicant
的可執(zhí)行文件,該可執(zhí)行文件提供了optee_os訪問
文件系統(tǒng)的RPC接口以及加載具體的TA鏡像的功
能。
xtest目標將會編譯optee_test目錄,生成在xtest
集合中會使用的TA鏡像文件和xtest可執(zhí)行文件。4.4.2 bios.bin鏡像的生成過程
bios.bin鏡像是啟動時會被使用到的主要鏡像文
件,在執(zhí)行make run-only指令使用QEMU方式啟動
OP-TEE時,會借助qemu-system-arm命令來啟動OP-
TEE和Linux kern,并掛載Linux的rootfs。在運行
qemu-system-arm命令時,其中有一個參數為“-
bios”,該參數就是告訴QEMU使用該參數之后所帶
的bios.bin來啟動整個系統(tǒng)。
bios.bin中會包含Linux kernel的鏡像、OP-TEE
OS的鏡像以及rootfs。該鏡像文件是在bios-qemu的
目標中編譯出來的。
當bios-qemu目標的依賴目標都編譯完成后,會
使用bios-qemu-common函數將Linux內核、OP-TEE
鏡像、rootfs打包成bios.bin鏡像文件。bios-qemu-
common函數定義在buildqemu.mk文件中,內容如
下:
define bios-qemu-common
+(MAKE) -C (BIOS_QEMU_PATH) CROSS_COMPILE=(CROSS_COMPILE_NS_USER) O=(ROOT)outbios-qemu BIOS_NSEC_BLOB=(LINUX_PATH)archarmbootzImage BIOS_NSEC_ROOTFS=(GEN_ROOTFS_PATH)filesystem.cpio.gz BIOS_SECURE_BLOB=(OPTEE_OS_BIN) PLATFORM_FLAVOR=virtEndef
執(zhí)行該函數時會帶入相關的編譯參數,編譯由
變量BIOS_QEMU_PATH定義的目錄
(bios_qemu_tz_arm目錄),參數說明如下:
·CROSS_COMPILE:編譯時使用的編譯參
數,包括編譯器、cflag等;
·O:編譯結果的輸出目錄;
·BIO_NSEC_BLOB:定義該變量,指定Linux
內核鏡像的名稱和路徑;
·BIOS_NSEC_ROOTFS:定義該變量,指定生
成的rootfs存在的目錄和cpio格式文件名;
·BIOS_SECURE_BLOB:定義該變量,指定
OP-TEE OS鏡像文件名;
·PLATFORM_FLAVOR:定義該變量,設定平
臺變量。
編譯bios_qemu_tz_arm目錄時最終會將Linux內
核鏡像、OP-TEE OS鏡像、rootfs轉換成.o文件,然
后再將這些轉換后的.o文件與其他的.o文件一起鏈
接成biso.bin鏡像文件。Linux內核鏡像文件會被放在bios.bin中名稱為nsec_blob的section里。OP-TEE
os image將會被放在bios.bin中名稱為secure_blob的
section里。rootfs image將會被放在bios.bin中名稱為
nsec_rootfs的section里。
上述將鏡像文件轉換成.o文件的操作是通過
OBJCOPY帶--rename-section參數來實現的,具體的
內容可以在link.mk文件中找到。
bios_qemu_tz_armbiosentry.s文件存放的就是
在啟動系統(tǒng)時bios.bin的入口文件。4.4.3 run-only目標的執(zhí)行
qemu.mk文件中的run-only目標是用來啟動使用
QEMU方式運行OP-TEE的起始目標,在qemu.mk文
件中,run-only目標的定義如下:
.PHONY: run-only
run-only:
(call check-terminal)
(call run-help)
(call launch-terminal, 54320,Normal World)
(call launch-terminal, 54321,Secure World)
(call wait-for-ports, 54320,54321)
(QEMU_PATH)arm-softmmuqemu-system-arm -nographic -serial tcp:localhost:54320 -serial tcp:localhost:54321 -s -S -machine virt -machine secure=on -cpu ARM核-a15 -m 1057 -bios (ROOT)outbios-qemubios.bin (QEMU_EXTRA_ARGS)
run-only目標的內容會調用各種函數,這些函
數會在相關的makefile文件中定義,下面是相關函
數的作用說明:
(call check-terminal):
check-terminal在QEMU的工程中不會被定義,該語句不會被執(zhí)行,但是在其他工程中會定義,具
體可查看buildcommon.mk文件。(call run-help):
run-help函數定義在buildcommom.mk文件中,主要用來打印出相關的啟動幫助信息。
(call launch-terminal,54320,Normal
World):
執(zhí)行l(wèi)aunch-terminal,54320,Normal
World指令,啟動名字為Normal World的terminal,其中l(wèi)aunch-terminal在buildcommon.mk文件中定
義。
(call launch-terminal,54321,Secure
World):
執(zhí)行功能同上,只是在重定向時將端口換成了
54321,且啟動的terminal名字為Secure World。
(call wait-for-ports,54320,54321):
調用wait-for-prots函數,該函數定義在
buildcommon.mk文件中,主要功能是檢查上面啟
動的兩個terminal使用socket方式進行通信是否正
常。
(QEMU_PATH)arm-softmmuqemu-system-arm:
該指令就是調用qemu-system-arm指令,并設定
好QEMU啟動的各種參數,然后開始啟動Linux與
OP-TEE,該指令完全展開之后的內容如下:
homeicyshuaidevelopteebuild..qemuarm-softmmuqemu-system-arm -nographic -serial tcp:localhost:54320 -serial tcp:localhost:54321 -s -S -machine virt -machine secure=on -cpu ARM核-a15 -m 1057 -bios homeicyshuaidevelopteebuild..outbios-qemubios.bin
-nographic:不顯示圖形界面。
-serial:將串口重定向到后面的參數部分。
-S:使用C來控制啟動(在QEMU的console界
面輸入C之后才會正式啟動系統(tǒng))。
-m:設定虛擬的內存大小。
-bios:指定BIOS的文件(該image中會包含
OP-TEE、Linux、rootfs的鏡像文件)。
1.launch-terminal函數
launch-terminal函數的主要功能是用來啟動terminal。該函數定義在buildcommon.mk文件中,具體內容如下:
define launch-terminal
@nc -z 127.0.0.1 (1) || (gnome-terminal) -t (2) -x (SOC_TERM_PATH)soc_term (1)
endef
(gnome-terminal)的定義也在common.mk文件
中,定義如下:
gnome-terminal := (shell command -v gnome-terminal 2>devnull)
調用(call launch-terminal,54320,Normal
World)等價于:
gnome-terminal -t Normal World -x (SOC_TERM_PATH)soc_term 54320
調用該函數的作用是啟動一個名字為Normal
World的terminal,并且在terminal中執(zhí)行soc_term
54320,soc_term就是在soc_term目錄中編譯出來的
可執(zhí)行文件。執(zhí)行soc_term 54320命令的主要作用
是將該terminal的輸入和輸出通過54320端口重定向
到標準輸入和輸出端口。
2.soc_term可執(zhí)行文件soc_term可執(zhí)行文件用來實現Linux和OP-TEE
的兩個terminal輸入和輸出重定向到標準輸入輸出
端口,該可執(zhí)行文件的源代碼存放在soc_term目錄
中。soc_term.c文件中的main函數定義如下:
int main(int argc, char argv[])
{
int listen_fd;
char port;
bool have_handle_telnet_option = false;
switch (argc) {
case 2:
port = argv[1];
break;
case 3:
if (strcmp(argv[1], -t) != 0)
usage;
have_handle_telnet_option = true;
port = argv[2];
break;
default:
usage;
}
save_current_termios;獲取當前terminal的信息(標準輸入輸出的terminal配置)
listen_fd = get_listen_fd(port);建立socket機制,并監(jiān)聽輸入的端口號
printf(listening on port %s\n, port);
if (have_handle_telnet_option) 判定是否使用telent
printf(Handling telnet commands\n);
進入loop循環(huán),完成端口監(jiān)聽和輸入輸出的重定向
while (true) {
int fd = accept_fd(listen_fd); 開始接收建立的監(jiān)聽端口的信息
handle_telnet = have_handle_telnet_option;
handle_telnet_codes(-1,NULL, NULL); 為使用telent時不起作用
warnx(accepted fd %d, fd);
復制當前terminal的信息,并配置其他參數,然后調用tcsetattr函數來設定當前啟動的terminal的信息
set_tty_noncanonical;
開始處理監(jiān)聽收到的數據,并根據對應的revent進行重定向操作,server_fd函數的注釋見后續(xù)章節(jié)
serve_fd(fd);
處理完成之后關閉該fd
if (close(fd)) err(1, close);
fd = -1;
保存當前terminos的配置
restore_termios;
}
}
server_fd函數用來接收受監(jiān)控的端口的數據,并執(zhí)行重定向操作,代碼內容和解釋如下:
static void serve_fd(int fd)
{
uint8_t buf[512];
struct pollfd pfds[2];
設定pollfd參數,用于實現重定向操作
memset(pfds, 0, sizeof(pfds));
pfds[0].fd = STDIN_FILENO;
pfds[0].events = POLLIN;
pfds[1].fd = fd;
pfds[1].events = POLLIN;
while (true) {
size_t n;
獲取監(jiān)聽事件的pfds[0]和pfds[1]中定義的事件
if (poll(pfds, 2, -1) == -1)
err(1, poll);
如果pfds[0]中的POLLIN時間觸發(fā)(在該terminal的標準輸入中有輸入操作),則進行讀取操作
if (pfds[0].revents POLLIN) {
從該terminal的標準輸入端口中讀取輸入的數據
n = read(STDIN_FILENO, buf, sizeof(buf));
if (n == -1)
err(1, read stdin);
if (n == 0)
errx(1, read stdin EOF);
將讀取到的數據寫入到重定向的port捆綁的socket
if (!write_buf(fd, buf, n)) {
warn(write_buf fd);
break;
}
}
如果pfds[1]中的POLLIN時間觸發(fā)(監(jiān)測到該terminal的port捆綁的socket有輸入流操作),則讀取監(jiān)測的port對應的socket句柄中的數據 if (pfds[1].revents POLLIN) {
讀取與port捆綁的socket的句柄中的數據
n = read(fd, buf, sizeof(buf));
if (n == -1) {
warn(read fd);
break;
}
if (n == 0) {
warnx(read fd EOF);
break;
}
handle_telnet_codes(fd, buf, n);
將讀取到的數據寫入到該terminal的標準輸出
if (!write_buf(STDOUT_FILENO, buf, n))
err(1, write_buf stdout);
}
}
}4.5 小結
本章主要介紹OP-TEE開發(fā)和運行環(huán)境的搭
建,并提供了一個demo,介紹如何開發(fā)自己的TA
和CA并讓其成功運行在OP-TEE中。為方便讀者理
解整個OP-TEE工程的實際執(zhí)行流程,知道如何生
成啟動OP-TEE時使用的各種鏡像文件,本章特意
介紹了OP-TEE工程的編譯過程以及編譯過程中各
種目標的依賴關系,同時對編譯過程中的重要函數
做了進一步的介紹。第二篇 系統(tǒng)集成篇
第5章 QEMU運行OP-TEE的啟動過程
第6章 安全引導功能及ATF的啟動過程
第7章 OP-TEE OS的啟動過程
第8章 OP-TEE在REE側的上層軟件
第9章 REE側OP-TEE的驅動第5章 QEMU運行OP-TEE的啟動過
程
使用QEMU的方式運行OP-TEE是通過在build
目錄下執(zhí)行make run-only來啟動的,啟動過程主要
是加載bios.bin文件,并從該鏡像文件中分離出
Linux內核鏡像和OP-TEE鏡像以及rootfs鏡像,并將
rootfs作為根文件系統(tǒng)掛到Linux系統(tǒng)中。本章將介
紹系統(tǒng)的啟動過程,并詳細介紹OP-TEE的啟動流
程和相關的重要啟動節(jié)點。5.1 bios.bin的入口函數
使用QEMU運行OP-TEE時首先加載的是編譯
生成的bios.bin鏡像文件,而bios.bin鏡像文件的入
口函數是在bios_qemu_tz_armbiosentry.S文件中定
義的,該文件的入口函數為_start,該文件的主要內
容如下:
.section .text.boot
定義 _start函數,設定第一條指令跳轉到reset函數執(zhí)行
FUNC _start , :
b reset
b . Undef
b . Syscall
b . Prefetch abort
b . Data abort
b . Reserved
b . IRQ
b . FIQ
END_FUNC _start
reset 函數
LOCAL_FUNC reset , :
read_sctlr r0
orr r0, r0, SCTLR_A
write_sctlr r0
設置中斷向量表
adr r0, _start
write_vbar r0
重新設定bios在RAM中的地址
mov r0, 0
ldr r1, =__text_start
ldr r2, =__data_end
sub r2, r2, r1
復制bios.bin文件中的__text_start到__data_end到地址為0的起始RAM中
bl copy_blob
跳轉到上面重新定位的bios在RAM中的地址 ldr ip, =new_loc
bx ip
new_loc:
重新設定中斷向量
adr r0, _start
write_vbar r0
清空BSS段的數據
ldr r0, =__bss_start
ldr r1, =__bss_end
sub r1, r1, r0
bl zero_mem
設定堆?臻g
ldr ip, =main_stack_top;
ldr sp, [ip]
push {r0, r1, r2}
mov r0, sp
ldr ip, =main_init_sec 獲取main_init_sec函數地址
blx ip 跳轉到main_init_sec函數中執(zhí)行,加載OP-TEE OS的image
pop {r0, r1, r2}
mov ip, r0 OP-TEE OS的入口地址
mov r0, r1 argument (address of pagable part if != 0)
blx ip 跳轉到OP-TEE OS的啟動地址
設置Normal World的棧
ldr ip, =main_stack_top;
ldr sp, [ip]
ldr ip, =main_init_ns 獲取main_init_ns函數的地址
bx ip 跳轉到main_init_ns函數,加載Linux內核的image
END_FUNC reset
復制函數
LOCAL_FUNC copy_blob , :
ldrb r4, [r0], 1
strb r4, [r1], 1
subs r2, r2, 1
bne copy_blob
bx lr
END_FUNC copy_blob
清空內存數據的函數
LOCAL_FUNC zero_mem , :
cmp r1, 0
bxeq lr
mov r4, 0
strb r4, [r0], 1
sub r1, r1, 1
b zero_mem
END_FUNC zero_memmain_init_sec函數用來將Linux內核鏡像、OP-
TEE OS鏡像、rootfs鏡像文件加載到RAM的對應位
置,并且解析出OP-TEE OS的入口地址、Linux內
核的加載地址、rootfs在RAM中的地址和其他相關
信息。main_init_sec函數執(zhí)行完成后會返回OP-TEE
OS的入口地址以及設備樹(device tree,DT)的地
址,然后在匯編代碼中通過調用blx指令進入OP-
TEE OS的啟動。
OP-TEE啟動完成后會重新進入entry.S文件中
繼續(xù)執(zhí)行,最終執(zhí)行main_init_ns函數來啟動Linux
內核,在main_init_sec函數中會設定Linux內核的入
口函數地址、DT的相關信息,main_init_ns函數會
使用這些信息來開始Linux內核的加載。
上述兩個函數都定義在
bios_qemu_tz_armbiosmain.c文件中。將各種鏡像
文件復制到RAM的操作都是通過解析bios.bin鏡像
的對應section來實現的,通過尋找特定的section來
確定各鏡像文件在bios.bin文件中的位置。5.2 OP-TEE鏡像的加載和啟動
啟動過程中entry.S文件通過匯編調用
main_init_sec函數將optee-os鏡像、Linux鏡像和
rootfs加載到RAM中,并定位DT的地址信息,以備
Linux和OP-TEE啟動使用,這些操作是由
main_init_sec函數進行的,該函數定義在
bios_qemu_tz_armbiosmain.c文件中,其內容如
下:
void main_init_sec(struct sec_entry_arg arg)
{
void fdt;
int r;
定義OP-TEE OS 鏡像文件存放的起始地址
const uint8_t sblob_start = __linker_secure_blob_start;
定義OP-TEE OS 鏡像文件存放的末端地址
const uint8_t sblob_end = __linker_secure_blob_end;
struct optee_header hdr; 存放OP-TEE OS image頭的信息
size_t pg_part_size; OP-TEE OS image除去初始化頭部信息的大小
uint32_t pg_part_dst; OP-TEE OS image除去初始化頭部信息后在RAM中的起始地址
msg_init; 初始化uart
加載device tree 信息。在qemu工程中,并沒有將device tree信息編譯到Bios.bin中,而默認存放在DTB_START地址中
fdt = open_fdt(DTB_START, __linker_nsec_dtb_start,__linker_nsec_dtb_end);
r = fdt_pack(fdt);
CHECK(r < 0);
判定OP-TEE OS image的大小是否大于image header的大小
CHECK(((intptr_t)sblob_end - (intptr_t)sblob_start) <
(ssize_t)sizeof(hdr));
將OP-TEE OS image header信息復制到hdr變量中
copy_bios_image(secure header, (uint32_t)hdr, sblob_start,sblob_start + sizeof(hdr));
校驗OP-TEE OS image header中的magic和版本信息是否合法
CHECK(hdr.magic != OPTEE_MAGIC || hdr.version != OPTEE_VERSION); msg(found secure header\n);
sblob_start += sizeof(hdr); 將sblob_start的值后移到除去image header的位置
CHECK(hdr.init_load_addr_hi != 0); 檢查OP-TEE OS的初始化加載地址是否為零
獲取OP-TEE OS除去 image header和ini操作部分代碼后的大小
pg_part_size = sblob_end - sblob_start - hdr.init_size;
確定存放OP-TEE OS除去image header和init操作部分代碼后存放在RAM中的地址
pg_part_dst = (size_t)TZ_RES_MEM_START + TZ_RES_MEM_SIZE - pg_part_size;
將存放OP-TEE OS除去image header和init操作部分后的內容復制到RAM中
copy_bios_image(secure paged part,pg_part_dst, sblob_start + hdr.init_size, sblob_end);
sblob_end -= pg_part_size; 重新計算sblo_end的地址,剔除page part
將pg_part_dst賦值給arg中的paged_part以備跳轉執(zhí)行OP-TEE OS使用
arg->paged_part = pg_part_dst;
將hdr.init_load_addr_lo賦值給arg中的entry,該地址為op-TEE OS的入口地址
arg->entry = hdr.init_load_addr_lo;
將OP-TEE OS的實際image復制到起始地址為hdr.init_load_addr_l的RAM地址中
copy_bios_image(secure blob, hdr.init_load_addr_lo, sblob_start,sblob_end);
復制kernel image、rootfs到RAM,并復制device tree到對應地址,以備被kernel使用
copy_ns_images;
將device tree的地址賦值給arg->fdt變量,以備OP-TEE OS啟動使用
arg->fdt = dtb_addr;
msg(Initializing secure world\n);
}
main_init_sec函數執(zhí)行后將會返回一個
sec_entry_arg的變量,該變量包含啟動OP-TEE OS
的入口地址、DT的地址以及paged_table的地址。
sec_entry_arg變量將會被entry.S文件用來啟動OP-
TEE OS,entry.S會將OP-TEE OS的入口地址保存在
r0寄存器中,而paged_table部分的起始地址會被保
存在r1寄存器中,將r0賦值給ip,最終entry.S文件
通過執(zhí)行blx ip指令進入OP-TEE OS的入口函數中去
執(zhí)行OP-TEE OS的啟動。當OP-TEE OS啟動完成之
后,entry.S文件會調用main_init_ns函數來啟動Linux內核。待Linux內核啟動完成之后,整個系統(tǒng)
也就啟動完成。5.3 Linux內核鏡像的加載和啟動
entry.S文件通過調用main_init_ns函數來完成對
Linux內核的啟動,該函數會調用call_kernel函數來
完成Linux內核的啟動,調用call_kernel函數時傳入
的參數說明如下:
kernel_entry:Linux內核在RAM中的入口地
址,該值在main_init_sec函數中通過調用
copy_ns_images函數來進行賦值。
dtb_addr:DT存放的位置,該值在
main_init_sec函數中通過調用copy_ns_images函數來
進行賦值。
rootfs_start:復制到RAM中的rootfs的起始地
址,該值在main_init_sec函數中被賦值。
rootfs_end:復制到RAM中的rootfs的末端地
址,該值在main_init_sec函數中被賦值。
call_kernel函數定義在
bios_qemu_tz_armbiosmain.c文件中,該函數的內
容和相關注釋如下:typedef void (kernel_ep_func)(uint32_t a0, uint32_t a1, uint32_t a2);
static void call_kernel(uint32_t entry, uint32_t dtb,uint32_t initrd, uint32_t initrd_end)
{
定義指向Linux內核入口地址的函數指針,并將函數指針的地址指向帶入參數entry的位置
kernel_ep_func ep = (kernel_ep_func)entry;
void fdt = (void )dtb; 定義device tree的地址并賦值
const char cmdline[] = COMMAND_LINE; 定義存放command line的變量并進行賦值
int r;
const uint32_t a0 = 0;
MACH_VEXPRESS see linuxarcharmtoolsmach-types
const uint32_t a1 = 2272;
獲取device tree的信息
r = fdt_open_into(fdt, fdt, DTB_MAX_SIZE);
CHECK(r < 0);
設置device tree中的相關節(jié)點、initrd的起始地址、initrd的末端地址、bootargs
setprop_cell(fdt, chosen, linux,initrd-start, initrd);
setprop_cell(fdt, chosen, linux,initrd-end, initrd_end);
setprop_string(fdt, chosen, bootargs, cmdline);
r = fdt_pack(fdt);
CHECK(r < 0);
打印相關信息
msg(kernel command line: \%s\\n, cmdline);
msg(Entering kernel at 0x%x with r0=0x%x r1=0x%x r2=0x%x\n,(uintptr_t)ep, a0, a1, dtb);
帶入device tree信息和其他相關參數,調用Linux內核的入口函數,進而執(zhí)行Linux內核的啟動
ep(a0, a1, dtb);
}
ep的值是Linux內核的入口函數指針,所以最
終調用ep(a0,a1,dtb)函數就能開始Linux內核的啟
動過程。5.4 rootfs的掛載
啟動Linux系統(tǒng)時會加載rootfs,rootfs在啟動
Linux系統(tǒng)之前會被拷貝到相應的內存地址中,系
統(tǒng)在啟動Linux時會告知Linux內核rootfs在內存中的
地址,Linux內核啟動時會到該地址中去獲取rootfs
的內容,掛載起來作為Linux系統(tǒng)的根文件系統(tǒng)使
用。5.5 OP-TEE驅動的啟動
在OP-TEE工程中,OP-TEE在REE側的驅動會
被編譯到Linux內核鏡像中,Linux系統(tǒng)在啟動的過
程中會自動掛載OP-TEE的驅動,驅動掛載過程中
會創(chuàng)建devtee0和devteepriv0設備,其中devtee0
設備將會被REE側的用戶空間的庫(libteec)使
用,devteepriv0設備將會被系統(tǒng)中的常駐進程
tee_supplicant使用,并且在OP-TEE驅動的掛載過程
中會建立正常世界狀態(tài)與安全世界狀態(tài)之間的共享
內存,用于OP-TEE驅動與OP-TEE之間的數據共
享,同時還會創(chuàng)建兩個鏈表,分別用于保存來自
OP-TEE的RPC請求和發(fā)送RPC請求的處理結果給
OP-TEE。5.6 tee_supplicant的啟動
tee_supplicant是Linux系統(tǒng)中的常駐進程,該進
程用于接收和處理來自OP-TEE的RPC請求,并將
處理結果返回給OP-TEE。來自OP-TEE的RPC請求
主要包括socket操作、REE側文件系統(tǒng)操作、加載
TA鏡像文件、數據庫操作、共享內存分配和注冊
操作等。該進程在Linux系統(tǒng)啟動過程中被自動創(chuàng)
建,在編譯時,該進程的啟動信息會被寫入
到etcinit.d文件中,而該進程的可執(zhí)行文件則被保
存在文件系統(tǒng)的bin目錄下。該進程中會使用一個
loop循環(huán)接收來自OP-TEE的遠程過程調用
(Remote Procedure Call,RPC)請求,且每次獲取
到來自OP-TEE的RPC請求后都會自動創(chuàng)建一個線
程,用于接收OP-TEE驅動隊列中來自OP-TEE的
RPC請求,之所以這么做是因為時刻需要保證在
REE側有一個線程來接收OP-TEE的請求,實現RPC
請求的并發(fā)處理。5.7 小結
本章介紹了使用QEMU的方式運行OP-TEE的
啟動過程,介紹了系統(tǒng)是如何啟動的,在啟動過程
中如何加載相應的鏡像文件。即使在非QEMU方式
運行OP-TEE時,OP-TEE的驅動和tee_supplicant同
樣會被掛載和啟動,這屬于運行OP-TEE不可或缺
的一部分。第6章 安全引導功能及ATF的啟動過
程
安全引導(Secure Boot)功能是指在系統(tǒng)的整
個啟動過程中,使用鏈式驗證電子簽名的方式來驗
證系統(tǒng)中重要鏡像文件的可靠性,然后再加載鏡像
文件的引導過程。安全引導功能可以保護二級廠商
系統(tǒng)的獨立性和完整性。在ARMv8架構中ARM提
供了ARM可信固件(ATF)。Bootloader、Linux內
核、TEE OS的啟動都由ATF來加載和引導。對于
ARMv8,Bootloader、Linux內核和TEE OS鏡像文
件的驗簽工作都是在ATF中完成的。本章將介紹安
全引導功能的原理以及ATF的啟動過程。6.1 安全引導的作用
安全引導可用于保證系統(tǒng)的完整性,防止系統(tǒng)
中重要鏡像文件被破壞或替換。一般情況下,安全
引導需要保護系統(tǒng)的BootLoader鏡像文件、TEE鏡
像文件、Linux內核鏡像文件、Recover鏡像文件以
及在ARMv8中使用的ATF鏡像文件。將TEE鏡像文
件的加載操作加入安全引導功能中可阻止黑客通過
替換TEE鏡像文件的方式來竊取被TEE保護的重要
資料。當前使用ARM芯片的系統(tǒng)中大部分使能了安
全引導功能,該功能對于用戶的最直接感受就是,當用戶非法刷入其他廠商的ROM后手機無法正常啟
動,這是因為非法刷機將導致系統(tǒng)中的重要鏡像文
件被替換,系統(tǒng)在啟動過程中對鏡像文件的電子驗
簽失敗,如果BootLoader驗證失敗,則系統(tǒng)在進入
BootLoader階段之前就會掛死。6.2 安全引導的原理
安全引導功能的原理就是采用鏈式驗簽的方式
啟動系統(tǒng),也就是在系統(tǒng)啟動過程中,在加載下一
個階段的鏡像之前都會對需要被加載的鏡像文件進
行電子驗簽,只有驗簽操作通過后,該鏡像才能被
加載到內存中,然后系統(tǒng)才會跳轉到下一個階段繼
續(xù)執(zhí)行,整個驗簽鏈中的任何一環(huán)驗簽失敗都會導
致系統(tǒng)掛死,系統(tǒng)啟動過程中的第一級驗簽操作是
由ChipRom來完成的。只要芯片一出廠,用戶就無
法修改固化在芯片中的這部分代碼,因此無法通過
修改第一級驗簽結果來關閉安全引導功能。而且驗
簽操作使用的RSA公鑰或者哈希值將會被保存在
OTPefuse中,該區(qū)域中的數據一般只有ChipRom和
TEE能夠讀取且無法被修改。RSA公鑰或者哈希值
將會在產品出廠之前被寫入到OTPefuse中,而且不
同廠商使用的密鑰會不一樣。
在谷歌的安全引導功能白皮書中提出了安全引
導功能實現方案的設計建議。谷歌建議將鏡像文件
的電子簽名信息和驗簽使用的RSA公鑰保存在電子
證書中,系統(tǒng)在啟動的過程中首先會驗證電子證書
的合法性,如果驗證通過則需從電子證書中獲取簽
名信息和RSA公鑰,然后再利用它們對鏡像文件進
行驗證。整個驗證過程就是先驗證證書,驗證證書通過后再去驗證鏡像文件的合法性。但是在實際實
現過程中,大多數芯片廠商是將簽名信息與需要被
驗簽的鏡像文件打包在一起,而RSA公鑰則會被打
包到執(zhí)行驗證操作的鏡像文件中。
不同廠商可能會對鏡像文件進行加密操作,使
保存在設備中的鏡像文件都是以密文的形式存在。
在啟動過程中,首先會驗證密文鏡像文件的合法性
然后再進行解密鏡像文件的操作,這些都完成后才
會將明文的鏡像文件加載到內存中然后再執(zhí)行跳轉
操作。6.2.1 ARMv7安全引導的過程
對于安全引導功能的實現和驗證過程各家芯片
公司的方案都不一樣,這是由該芯片的啟動流程以
及啟動所需鏡像文件來決定的,但都會遵循鏈式驗
簽啟動的原則。ARMv7架構并沒有使用ATF,系統(tǒng)
的啟動流程與以前一樣使用BootLoader來引導Linux
內核和TEE OS。安全引導的啟動流程如圖6-1所
示。圖6-1 安全引導的啟動流程
系統(tǒng)啟動過程使用鏈式驗簽的方式進行引導,其中任何一環(huán)驗簽失敗都會導致系統(tǒng)啟動失敗,為
防止通過替換ramdisk來修改根文件系統(tǒng)中的內容,一般將ramdisk與Linux內核打包在同一個鏡像文件
中,而且該鏡像文件需要待驗簽通過后才可被使
用。簽名信息一般是對鏡像文件的內容進行哈希計
算獲取摘要后再對該摘要使用RSA私鑰進行電子簽
名來獲得,驗證時同樣會計算需要被引導的鏡像文
件的摘要,然后使用該摘要、簽名信息以及RSA公
鑰進行RSA算法的驗證。6.2.2 ARMv8安全引導的過程
ARMv8架構之后ARM提供了ATF,BootLoader、TEE鏡像文件、Linux內核鏡像文件、recovery鏡像文件都是由ATF來進行引導和加載而
不是由ChipRom來完成的。ChipRom只會去驗證
ATF中bl1的合法性,后續(xù)引導過程同樣也是按照鏈
式驗簽的方式進行,符合TBBR規(guī)范。讀者可使用
git命令從gitHub上獲取ATF的所有源代碼[1]。在
ARMv8架構中整個安全引導的流程如圖6-2所示。圖6-2 ARMv8的Secure Boot流程
ARMv8架構中引入了ATF,同時在ATF中提供
了安全引導的功能,BootLoader鏡像、Linux內核、recovery鏡像和TEE OS鏡像文件的簽名方式都由
ATF決定。當然開發(fā)者也可以對ATF進行定制化,修改ATF中的驗簽過程,但是修改后的驗簽方案需
要符合TBBR規(guī)范。
[1] ATF的git倉庫鏈接可參閱ATF源代碼鏈接:
https:github.comlinaro-swgarm-trusted-firmware。6.3 ATF的啟動過程
ATF的啟動過程根據ARMv8的運行模式
(AArch32AArch64)會有所不同,但基本一致。
在AArch32中是不會去加載bl31而是將EL3或者
Monitor模式的運行代碼保存在bl32中執(zhí)行。在
AArch64中,ATF的完整啟動流程如圖6-3所示。
圖6-3 AArch64模式的ATF啟動流程
在上述啟動過程中,從一個鏡像跳轉到另外一
個鏡像文件執(zhí)行的方式各不相同,以下為鏡像跳轉的過程和方式說明。
1.bl1跳轉到bl2執(zhí)行
在bl1完成了將bl2鏡像文件加載到RAM中的操
作、中斷向量表的設定以及其他CPU相關設定后,bl1_main函數會解析出bl2鏡像文件的描述信息,獲
取入口地址,并設定下一個階段的cpu上下文。這
些操作完成之后,調用el3_exit函數來實現bl1到bl2
的跳轉,進入bl2中開始執(zhí)行。
2.bl2跳轉到bl31執(zhí)行
在bl2中將會加載bl31、bl32、bl33的鏡像文件
到對應權限的內存中,并將該三個鏡像文件的描述
信息組成一個鏈表保存起來,以備bl31啟動bl32和
bl33使用。在AArch64中,bl31為EL3的執(zhí)行軟件,其運行時的主要功能是對安全監(jiān)控模式調用
(smc)指令和中斷處理,運行在ARM的Monitor模
式中。
bl32一般為TEE OS鏡像文件,本章以OP-TEE
為例進行說明。
bl33為正常世界狀態(tài)的鏡像文件,例如uboot、EKD2等。當前該部分為BootLoader部分的鏡像文
件,再由BootLoader來啟動Linux內核鏡像。從bl2跳轉到bl31是通過帶入bl31的入口點信息
作為參數,然后調用安全監(jiān)控模式調用指令,觸發(fā)
在bl1中設定的安全監(jiān)控模式調用請求,該請求處理
完成后會將中央處理器的執(zhí)行權限交給bl31,并跳
轉到bl31中去執(zhí)行。
3.bl31跳轉到bl32執(zhí)行
在bl31中會執(zhí)行runtime_service_inti函數,該函
數會調用注冊到EL3中所有服務的初始化函數,其
中有一個服務項就是TEE服務,該服務項的初始化
函數會將TEE OS的初始化函數賦值給bl32_init變
量,當所有服務項執(zhí)行完初始化后,在bl31中會調
用bl32_init執(zhí)行的函數來跳轉到TEE OS中并開始執(zhí)
行TEE OS的啟動。
4.bl31跳轉到bl33執(zhí)行
當TEE-OS鏡像啟動完成后會觸發(fā)一個ID為
TEESMC_OPTEED_RETURN_ENTRY_DONE的安
全監(jiān)控模式調用,該調用是用來告知EL3 TEE OS
鏡像已經完成了初始化,然后將CPU的狀態(tài)恢復到
bl31_init的位置繼續(xù)執(zhí)行。
bl31通過遍歷在bl2中記錄的所有鏡像信息的鏈
表來找到需要執(zhí)行的bl33的鏡像。然后通過獲取到bl33鏡像的信息,設定下一個階段的CPU上下文, ......
您現在查看是摘要介紹頁, 詳見PDF附件(18090KB,786頁)。
指南_1.jpg)
指南_2.jpg)
指南_3.jpg)
指南_4.jpg)
指南_5.jpg)
指南_6.jpg)