Android verified boot 2.0 vbmeta 數據結構解析

驗證啓動(Verified Boot)是Android一個重要的安全功能,主要是爲了訪問啓動鏡像被篡改,提高系統的抗攻擊能力,簡單描述做法就是在啓動過程中增加一條校驗鏈,即 ROM code 校驗 BootLoader,確保 BootLoader 的合法性和完整性,BootLoader 則需要校驗 boot image,確保 Kernel 啓動所需 image 的合法性和完整性,而 Kernel 則負責校驗 System 分區和 vendor 分區。

由於 ROM code 和 BootLoader 通常都是由設備廠商 OEM 提供,而各家實際做法和研發能力不盡相同,爲了讓設備廠商更方便的引入 Verified boot 功能,Google 在 Android O上推出了一個統一的驗證啓動框架 Android verified boot 2.0,好處是既保證了基於該框架開發的verified boot 功能能夠滿足 CDD 要求,也保留了各家 OEM 定製啓動校驗流程的彈性。

由於 ROM code 校驗 BootLoader 的功能通常與 IC的設計相關,所以 AVB 2.0 關注的重點在 BootLoader 之後的校驗流程。BootLoader 之後系統啓動所涉及的關鍵鏡像通常包括 boot.img,system.img,Android O 的 treble Project 還引入了 dtbo 和 vendor.img。這些 image 挨個校驗可以說費時費力,而 AVB 2.0 的做法事實上十分簡單,引入一個新的分區:vbmeta.img(verified boot metadata),然後把所有需要校驗的內容在編譯時就計算好打包到這個分區,那麼啓動過程中 BootLoader 只需要校驗 vbmeta.img,就能確認 vbmeta 內的數據是否可信。再用 vbmeta 中的數據去比對 bootimg,dtbo,system,img,vendor.img 即可。至於 OEM 是還需要放什麼其他東西到 vbmeta 中,則可以由 OEM 自由定製,可以說保留了很好的客製化空間。

除了最基本的驗證啓動之外,AVB 2.0 還提供防止回滾的功能和對AB分區備份的支持,AVB 2.0 的詳細文檔可以參考:Android Verified Boot 2.0

無論是驗證啓動還是防止回滾,vbmeta 都是很重要的數據結構,下面對最簡單的 vbmeta struct 做一個分析說明。
下面是 vbmeta struct 的結構圖示:

以上 vbmeta 所包含的數據可以分成兩個大的Block:紫色色塊部分爲 Authentication data block 和 其他爲 Auxiliary data block。當 BOARD_AVB_ALGORITHM 定義爲 SHA256_RSA2048 時,默認編譯出的 vbmeta.img 通常爲 4KB。vbmeta.img 組成如下:

------------------------------------------------------------------------------
|   Header   |   Authentication Data   |    Auxiliary Data    |
------------------------------------------------------------------------------

其中 Header 的固定長度爲 0x100 個字節,Authentication data 和 Auxiliary data 的長度存儲在 Header 中。

下面分別對這三個部分進行分析、

Header 解析

Header 的數據結構爲:typedef struct AvbVBMetaImageHeader
用 UE 打開 vbmeta.img,前 0x100 個字節信息如下:


根據 struct AvbVBMetaImageHeader,上圖中的 Header 信息解析如下:

Authentication data block 解析

Authentication data block 用於校驗 vbmeta.img 的合法性和完整性,包含兩部分內容:Hash data 和 signature data。
通過分析avbtool 的 Python 腳本,即可瞭解 hash data 和 signature data 的生成過程。

     Hash data 的生成
     hash data 是對 vbmeta 的 header 和 auxiliary data block 的 hash 計算,所以是先生成了 auxiliary data block,然後生成的 authentication data block,使用的算法由 header 中的 algorithm_type 指定,本文使用 SHA256,計算出的 hash data 長度爲 0x20。截取 avbtool 的腳本代碼如下:

# Calculate the hash.

ha = hashlib.new(alg.hash_name)

ha.update(header_data_blob)

ha.update(aux_data_blob)

binary_hash.extend(ha.digest())

signature data 的生成
     signature data 是對 上文計算出的 hash data 做 padding 之後的簽名,使用的算法同樣由 header 中的 algorithm_type 指定,本文使用 RSA2048,計算出的 signature data 長度爲 0x100。截取 avbtool 的腳本代碼如下:

# Calculate the signature.

padding_and_hash = str(bytearray(alg.padding)) + binary_hash

binary_signature.extend(raw_sign(signing_helper, signing_helper_with_files, algorithm_name, alg.signature_num_bytes, key_path, padding_and_hash))

有一個需要注意的地方是,hash data 和 signature data 的總長加在一起爲0x120,但header 中的 authentication data block size 卻爲 0x140,這是因爲 image 對齊需要,0x120 不能被 64 整除,所以用 0x0 填充到長度爲 0x140。

Auxiliary data block 解析

Auxiliary data block 的內容則十分豐富,總得來說分爲兩個大類:AvbDescriptor 和 RSA public key。

     AvbDescriptor 的生成
根據 avbtool make_vbmeta_image 命令支持的參數,OEM 可以自由的定製一些需要打包到 vbmeta.img 的數據,這樣一段一段的二進制數據都按照AvbDescriptor 的數據結構打包進 auxiliary data block。AvbDescriptor 按照不同的 tag 分爲以下幾種:

typedef enum {
        AVB_DESCRIPTOR_TAG_PROPERTY,
        AVB_DESCRIPTOR_TAG_HASHTREE,
        AVB_DESCRIPTOR_TAG_HASH,
        AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
        AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
} AvbDescriptorTag;

最常用的參數 ---include_descriptor_from_image 可以將 boot.img,dtbo,recovery.img,system.img,vendor.img 的 descriptor 打包到 Auxiliary data block 中。這些 descriptors 在 BootLoader 確認 vbmeta.img 的合法性和完整性後,可以直接被用來校驗 boot.img,dtbo,recovery.img,system.img,vendor.img。

     RSA public key的生成
除了這些 descriptor 之外,auxiliary data block 中還有一個重要的信息,就是 RSA public key。這個 public key 將被用來校驗 authentication data block 中的 signature data。
在 avbtool make_vbmeta_image 時,必須用--key參數來指定生成 signature data 的 RSA private key,AOSP external/avb/test/data 目錄下有各種供測試使用 RSA private key,格式爲 PEM。avbtool 會根據 RSA private key 提取 public key 並加上 RSA key 的 header 打包進 auxiliary data block。
可以通過avbtool extract_public_key --key [priv_key_path] --output [outpubk_path] 來查看生成的 public key 信息。
其中 RSA key header 格式如下:

typedef struct AvbRSAPublicKeyHeader {
         uint32_t key_num_bits;
         uint32_t n0inv;
} AVB_ATTR_PACKED AvbRSAPublicKeyHeader;

前文中所描述 header 中的 public key size 爲 0x208,即 0x8 個字節的 AvbRSAPublicKeyHeader 長度,加上 0x200個字節即 2048位 的 public key 長度。

以上就是 vbmeta 除 padding 填充 0x0 之外,主要的數據信息。

 

 

 

 

 

 

 

 

 


作者:SmartEmily
鏈接:https://www.jianshu.com/p/a2542426bdde
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

作者:SmartEmily
鏈接:https://www.jianshu.com/p/a2542426bdde
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章