1. 程式人生 > >android dm-verity 功能【轉】

android dm-verity 功能【轉】

轉自:https://blog.csdn.net/ee230/article/details/73348344

Android dm-verity 實現原理深入研究

思維導圖:

dm-verifydm-verity

 

說明:原始碼基於 SC20 平臺 Android5.1
Android dm-verify overview

目錄

Android dm-verify overview.. 1

一、原理… 1

與Verified Boot關係… 1

dm-verity. 1

作用分割槽… 2

二、模組結構… 2

1.簽名… 2

生成OEM自己的金鑰對… 4

驗籤… 5
使用者空間,android 部分… 5

核心空間… 5

三、如何啟用… 5

四、測試… 6

測試樣例1. 無法 remount, 無法 push 檔案… 6

測試樣例2. 6

五、存在風險… 6

物理塊出現壞塊… 6

六、其他… 6

七、參考文件… 6

一、原理

與Verified Boot關係

Verified Boot 是 Android 4.4 開始引入的一個新特性,配合可選的 dm-verify 功能,可以檢測系統是否被篡改,以此儲存系統的完整性。

dm-verity

dm-verity 基於kernel 的 Device mapper 框架,Device mapper 是 Linux 2.6 核心中提供的一種從邏輯裝置到物理裝置的對映框架機制,在該機制下,使用者可以很方便的根據自己的需要制定實現儲存資源的管理策略。關於 Device mapper,可以參考此文獻

https://www.ibm.com/developerworks/cn/linux/l-devmapper/

dm-verity 用一個 hash 樹來描述整個 system 映象。這種機制允許 system 分割槽在讀寫的時候進行校驗,而不是一次性將整個 system 映象進行校驗。當校驗 hash 值不一致的時候,返回 IO 錯誤

框架示意圖:

dm-verity-hash-treedm-verity-hash-tree

 

 作用分割槽

system

vendor

OEM

其他只讀分割槽

二、模組結構

 1.簽名

如何生成用於dm-verity 校驗的映象,可以參考一下主流程:

主流程,Android 官方文件如下:

– Generate an ext4 system image.

– Generate a hash tree for that image.

– Build a dm-verity table for that hash tree.

– Sign that dm-verity table to produce a table signature.

– Bundle the table signature and dm-verity table into verity metadata.

– Concatenate the system image, the verity metadata, and the hash tree.

  • 生成 ext4 格式的 system 映象
  • 生成 system 映象的 hash 樹
  • 根據 hash 樹生成 dm-verity table
  • 對 dm-verity 進行簽名,得到簽名檔案
  • 將簽名、dm-verity table 打包到 metadata 映象
  • 將 verity metadata,hash 樹 新增到 system 映象末尾
  • 生成 ext4 格式的 system 映象
    build/tools/releasetools/build_image.py  BuildImage 函式 中

通過 prop_dict 屬性,判斷是否啟用 verity 功能,啟用的話,調整 system 分割槽大小,以便後面新增相關檔案到 system.img 末尾,然後 RunCommand(build_command) 生成初始的 system.img。

prop_dict 檔案路徑:

out/target/product/msm8909/obj/PACKAGING/systemimage_intermediates/system_image_info.txt

prop_dict 檔案內容:

fs_type=ext4

system_size=1288491008

userdata_size=4831838208

cache_fs_type=ext4

cache_size=268435456

extfs_sparse_flag=-s

selinux_fc=out/target/product/msm8909/root/file_contexts

verity=true

verity_key=build/target/product/security/verity

verity_signer_cmd=out/host/linux-x86/bin/verity_signer

system_verity_block_device=/dev/block/bootdevice/by-name/system

skip_fsck=true

  • 生成 system 映象的 hash 樹

BuildVerityTree 函式生成 hash tree (verity_image)

步驟3,4,5在BuildVerityMetadata中實現,BuildVerityMetadata 呼叫build_verity_metadata.py 來實現

BuildVerityMetadata 生成 metadata (metadata_image),

跳轉到 system/extras/verity/build_verity_metadata.py

  • 根據 hash 樹生成 dm-verity table

build_verity_table 生成 dm-table

dm-table 其實就是一個字串

  • 對 dm-verity 進行簽名,得到簽名檔案

sign_verity_table 將 dm-table 簽名

signer_key = build/target/product/security/verity.pk8

  • 將簽名、dm-verity table 打包到 metadata 映象

build_metadata_block 將 dm-table 和 簽名信息打包,寫入 datameta.img

  • 將 verity metadata,hash 樹 新增到 system 映象末尾

build/tools/releasetools/build_image.py  BuildVerifiedImage 生成最終的可以用於 dm-verity 校驗的映象

Append2Simg 新增 verity_image 和 datameta.img 到 system.img 末尾

其他

FIXED_SALT 可以修改為自己的 salt

如何生成自己的oem key

dm-verity 相關的金鑰

build/target/product/security/ build/target/product/verity.mk verity.pk8 – 私鑰,用於簽名 boot.img 和 system.img

verity.x509.pem – 包含公鑰的證書

verity_key – 公鑰,dm verity 中用於驗籤 system 分割槽

   生成OEM自己的金鑰對

  1. HSM(Hardware Security Module)
  1. OpenSSL tool
  • 生成新得金鑰對 >openssl version OpenSSL 1.0.2d 9 Jul 2015 >development/tools/make_key mykey ‘/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/[email protected]
  • 為DM-Verity 功能生成 verity key
    1. 使用下面的命令來生成 verity key 的工具 generate_verity_key: source build/envsetup.sh choosecombo make generate_verity_key (mmm system/extras/verity/)
    2. 將 *.x509.pem 轉換成 verity key generate_verity_key 的程式碼位於:system/extra/verity/generate_verity_key.c generate_verity_key 的用法:generate_verity_key | -convert 例項: out/host/linux-x86/bin/generate_verity_key -convert mykey.x509.pem verity_key
  • 拷貝並重命名
    1. 拷貝pk8,mykey.x509.pem,verity_key.pub 至 build/target/product/security/ 目錄,將其重新命名: verity.pk8, verity.x509.pem,verity_key ,並替換預設的開發 key。
  • 生成 keystore
    1. 執行下面的兩個命令,生成img openssl rsa -in mykey.pk8 -inform DER -pubout -outform DER -out mypub.der java -Xmx512M -jar out/host/linux-x86/framework/KeystoreSigner.jar mykey.pk8 mykey.x509.pem keystore.img mypub.der
    2. 通過下面的指令碼將img生成oem_keystore.h檔案,shell 輸入: function generate_oem_keystore_h() { echo \#ifndef __OEM_KEYSTORE_H echo \#define __OEM_KEYSTORE_H xxd -i $1 | sed -e ‘s/unsigned char .* = {/const unsigned char OEM_KEYSTORE[] = {/g’ -e ‘s/unsigned int .* =.*;//g’ echo \#endif }
  • generate_oem_keystore_h keystore.img > oem_keystore.h
  • 將該h檔案拷貝到:bootable/bootloader/lk/platform/msm_shared/include
  1. 驗籤

使用者空間,android 部分

相關檔案:

system/core/fs_mgr/fs_mgr_verity.c

使用者空間對 dm-verity 進行初始化,驗籤 hash_table 的簽名,傳入 hash_table 等引數

核心空間

相關檔案:

KERNEL_SRC/driver/md/dm-verity.c 相關程式碼

核心空間根據使用者空間傳入的引數,進行初始化

當有 IO 操作時,對相應 data block 進行驗籤。

data block 讀取時,不僅當前 data block 需要 hash 校驗,上一層的 hash block 也需要進行校驗,直到root hash。

每一個 data block 如果已經驗簽過,再次讀取時就不用進行層層的校驗,只校驗當前 data block 的 hash 是否正確即可。

三、如何啟用

  1. kernel 配置檔案使能 CONFIG_DM_VERITY

kernel/arch/arm/configs/msm8909-1gb_defconfig

  1. Android 相關 mk 檔案配置

device/qcom/msm8909/msm8909.mk PRODUCT_SUPPORTS_VERITY := true PRODUCT_SYSTEM_VERITY_PARTITION := /dev/block/bootdevice/by-name/system

  1. 更新 fstab,system 分割槽新增 verify 標誌

/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1 wait,verify

  1. 編譯 userdebug 或者 user 版本 boot.img 以及 system.img,燒錄

四、測試

測試樣例1. 無法 remount, 無法 push 檔案

Mount | grep system /dev/block/dm-0 /system ext4 ro, seclable, relatime, data=ordered 0 0

adb pull /fstab.qcom c:\temp\fstab, 檢查 verify 標誌: /dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1 wait, verify

adb remount Use “adb disable-verity” to disable verity. If you do not, remount may succeed, however, you will still not be able to write to these volumes. remount of system failed: Read-only file system remount failed

 測試樣例2.

(1).先燒錄啟用 verity 功能的 boot.img 和 system.img

(2). 然後燒錄未啟用 verity 功能的 boot.img,重啟後 push 一個 apk 到 /system/app/ 目錄

(3). 重新燒錄啟用了 verity 功能的 boot.img,重啟後,機器無法開機,kernel log 可以看到 data block xxx is corrupted

五、存在風險

 物理塊出現壞塊

  1. 開機檢驗出錯,無法開機
  2. 開機檢驗沒問題,讀取檔案出錯,返回 Error IO

六、其他

軟體整合和 OTA 升級,必須使用 block 方式生成 OTA 升級包,需要注意適配。

 七、參考文件

Verified Boot

https://source.android.com/security/verifiedboot/index.html

Verifying Boot

https://source.android.com/security/verifiedboot/verified-boot.html

Implementing dm-verity

https://source.android.com/security/verifiedboot/dm-verity.html

Dmverity

https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity

dm-table format

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/device-mapper/verity.txt

Device mapper

https://www.ibm.com/developerworks/cn/linux/l-devmapper/

轉載:http://kevinems.com/software-development/600.html