1. 目的/背景
此文檔使用了secure boot 2.1方案的配置,如有其他版本的secure方案,本文檔僅作參考,secure boot方案可在security MTK文檔中查到,也可以諮詢MTK,此文檔適配於:MTK6739等平臺。
2. 前述
Secure boot & Efuse方案和硬件強相關,在開始調試之前切記以下要點:
1. 確保所有的keys都是一次性生成的,keys、證書、hash一定要匹配,如果不確定,請全部重新生成一次
2. 生成keys之後謹慎保存,如無必要,儘量不做修改(尤其是root_key),修改之後,以前efuse的芯片便無法再使用。
3. 再所有方案double 驗證OK之前,不要上傳secure boot的開關宏,以免造成大面積芯片廢棄
3. 可參考文檔
Secure_2.1_Configuration_SOP.pdf
Efuse_self_blow_user_guide_v1.3.pdf
4. 詳細配置方案
生成keys
利用openssl生成private key和publickey,並用pem_to_der.pyiaoben轉換key的格式爲pem
生成private key:
opensslgenrsa -out root_prvk.pem 2048
/*rsa是格式,2048是長度,目前在MTK都保持這樣的格式*/
轉換格式:
pythonpem_to_der.py root_prvk.pem root_prvk.der
生成public key
opensslrsa -in root_prvk.pem -pubout > root_pubk.pem
轉換格式:
pythonpem_to_der.py root_pubk.pem root_pubk.der
生成img key,用來簽名和校驗img
openssl genrsa -out image_prvk.pem 2048
以上操作如下面演示:
產生oemkey.h和dakey.h
用der_extractor腳本將root key(root_pubk.der)導出生成oemkey.h,然後放到下面三個目錄
生成命令:
./der_extractor root_pubk.der oemkey.h ANDROID_SBC
生成方式如圖:
【DA】DA的生成交給Tool team,SW只需要提供oemkey.h給工具組即可
【PL】:$PL/custom/$project/inc/oemkey.h
【LK】:$LK/target/$project/inc/oemkey.h
同樣的方式將root_pubk.der導出生成dakey.h
功能:dakey.h中包含的DA_PLpublic key public key用於preloader校驗DA_PL.bin,所以在簽名DA_PL.bin時需要拿這個key對應的private key對DA_Pluo簽名
Note:值得注意的是,由於DA_PL下載權限很低,所以通常我們的DA都使用DA_BROM的方式去做下載,但是推薦此處同樣配置OK。
dakey和oemkey都是用同樣的pubk key生成的,所以生成出來的dakey和oemkey都是相同的,但是在dakey中需要修改部分內容,否則會導致編譯報錯:
Dakey.h生成後存放位置:
【PL】:$PL/custom/$project/int/dakey.h
Secure boot配置部分
Preloader配置:
vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/$project/$project.mk
MTK_SECURITY_SW_SUPPORT=yes
MTK_SEC_BOOT=
MTK_SEC_USBDL=
Note:上述兩個BOOT和USBDL宏如果是SW root of trust,意味着,硬件上不實現efuse,但sw上要強制打開secure boot和securitydownload,那麼需要如下配置:
MTK_SEC_BOOT=ATTR_SBOOT_ENABLE
MTK_SEC_USBDL=ATTR_SUSBFL_ENABLE
如果是hw root of trust,意味着會燒寫efuse,並在efuse後打開secure boot和secure download,需要如下配置(默認)
MTK_SEC_BOOT=ATTR_SBOOT_ONLY_ENABLE_ON_SHIP
MTK_SEC_USBDL=ATTR_SUSBDL_ONLY_ENABLE_ON_SHIP
vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/$project_name/cust_bldr.mk
MTK_EFUSE_WRITER_SUPPORT :=yes/*注意定義的格式*/
MTK_EFUSE_WRITER_RESERVE_CODESIZE := yes
CFG_USB_AUTO_DETECT := 1 //注意這個宏,此宏定義生效,下載階段強制枚舉BROM端口,DA和AUTH將在這裏校驗,如果該宏沒有定義,會導致端口錯誤
~/vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mtxxxx/src/security/inc/sec_efuse.h
#define EFUSE_BLOW_KEY1 0x90b1e2f6 //此爲MTK默認值,建議修改定製
#define EFUSE_BLOW_KEY2 0x73d5a8c9
該項和input.xml中的magic key對應,在input.xml中詳細解釋配置方法
Lk配置
vendor/mediatek/proprietary/bootable/bootloader/lk/project/$project.mk
MTK_SECURITY_SW_SUPPORT=yes
MTK_EFUSE_WRITER_SUPPORT :=yes
Note:此處有兩個宏是可選的,如需支持fastbootunlock的命令,可以將此處打開,但目前和MTK溝通,此功能開發尚未完全,需要自行定製,建議在調試該功能時先關閉。否則通過fastboot刷機會有風險。
MTK_SEC_FASTBOOT_UNLOCK_SUPPORT
MTK_SEC_FASTBOOT_UNLOCK_KEY_SUPPORT
Kernel配置:
根據project選項defconfig配置,需要確定是用arm32還是arm64:
kernel-4.x/arch/arm/configs/
在所有項目的defcofnig和def_debug_cofnig中添加:
MTK_SECURITY_SW_SUPPORT=yes
DEVICE配置
Device/mediatek/$project/ProjectConfig.mk
MTK_EFUSE_WRITER_SUPPORT=yes
Preloader簽名:
Build cert_chain格式的preloader是在build的過程中sign的,那麼簽名的配置是使用cert_chain簽名格式:
1.將生成的root key(包括root_prvk.pem , img_prvk.pem)cp到以下路徑:
~/vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/security/chip_config/s/key/
配置宏配置sign preloader的pem路徑:
Pl_content.ini 中配置imgkey路徑:
Note:上述兩個ini中sw_ver版本號需要一致
Pl_gfh_config_cert_chain.ini配置
注意:裏面的version等其他信息,請不要隨意更改
使用python形式的sign tool配置
先確定該路徑:~/vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/security/chip_config/s/cfg下的PBP_BY_SUPPORT文件是否存在,如果遇到不存在的,請重新同步或者向MTK索要
Padding type的配置
確定同樣路徑下:
/vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/security/chip_config/s/cfg/
的PADDING_TYPE.ini中是否有設置:
Cert_chain /*代表生成preloader的格式是以cert_chain格式的*/
Resign preloader,secure 2.1支持在build的過程中去簽名preloader,也支持對已簽名的鏡像進行re-sign
簽名流程檢測:
產生cert1和cert2
用security2.1生成的root_prvk.pem和image_prvk.pem產生cert1和cert2_key
檢查SecureGen.py腳本中幾個關鍵點,如果沒有需要自己添加:
/vendor/mediatek/proprietary/scripts/sign-image_v2/SecureGen.py
def genCert1(binList)
....
if ( isMD == 0):
if(argDict["root_key_padding"]):
sh_command= "python "+ resign_tool_path+ " type=cert1 privk="+argDict["cert1_key_path"] +"pubk="+cert2_pubk_path+" ver="+str(img_ver)+"group="+str(img_group)+" root_key_padding="+str(argDict["root_key_padding"])
else:
sh_command= "python "+ resign_tool_path+ " type=cert1 privk="+argDict["cert1_key_path"] +"pubk="+cert2_pubk_path+" ver="+str(img_ver)+" group="+str(img_group)
tmp_out_path= out_cert1_path
else:
mdBin =os.path.join(out, part_name+".img")
if(os.path.isfile(mdBin) ):
printmdBin+" exist"
if(argDict["root_key_padding"]):
sh_command= "python "+ resign_tool_path+ " type=cert1mdimg="+mdBin+" privk="+argDict["cert1_key_path"]+" pubk="+cert2_pubk_path+" ver="+str(img_ver)+"group="+str(img_group)+" root_key_padding="+str(argDict["root_key_padding"])
else:
sh_command= "python "+ resign_tool_path+ " type=cert1md img="+mdBin+"privk="+argDict["cert1_key_path"] +"pubk="+cert2_pubk_path+" ver="+str(img_ver)+"group="+str(img_group)
tmp_out_path= out_cert1md_path
else:
printmdBin+" Not exist"
print"Bypassmd image cert1 Gen!"
執行以下命令
./ vendor/mediatek/proprietary/scripts/sign-image_v2/SecureGen.py mt67xx cert1_key_path=${KEY_PATH}/root_prvk.pem cert2_key_path=${KEY_PATH}/img_prvk.pem root_key_padding=pss | tee securegen.log
以上KEY_PATH=指存放root_prvk.pem和img_prvk.prm的路徑
說明:
請在codebase的根目錄下使用該腳本,包括簽名腳本,否則無法加載到環境參數
根據cert1_key_path的key,生成所有的img的cert1到
/vendor/mediatek/proprietary/custom/security/cert_config/cert1
根據cert2_key_path的key,生成所有的image的cert2到:
/vendor/mediatek/proprietary/custom/security/cert_config/cert2_key/
執行完secureGen.py後,請檢查上面目錄文件是否更新
建議保留gen的log,以防doubleconfirm時沒有參照依據。
產生簽名的image
Cert2和cert2的key正確產生之後,就可以執行簽名腳本,產生xx-verified.bin/img了,執行如下命令進行簽名:
./vendor/mediatek/proprietary/scripts/sign-image_v2/SignFlow.py $platform $project | tee sign.log
或者
vendor/mediatek/proprietary/scripts/sign-image/sign_image.sh
build DA
提供oemkey.h生成DA_BR.bin,詳細生成DA的情況在window下進行,詳細請參考文檔
SignDA的配置
Security2.1的DA需要使用python腳本進行簽名
Key的配置:
所有對DA簽名,生成auth和secrtfile的keys都放在:
~/vendor/mediatek/proprietary/scripts/secure_chip_tools/keys/下,如下:
drwxr-xr-x 2 keli cdgroup 4096 Dec 19 11:30 hsm/
drwxr-xr-x 2 keli cdgroup 4096 Dec 19 11:30 pbp/
drwxr-xr-x 2 keli cdgroup 4096 Dec 19 17:29 resignda/————對應DA
drwxr-xr-x 2 keli cdgroup 4096 Dec 19 11:33 sctrlcert/————對應secrtfile
drwxr-xr-x 2 keli cdgroup 4096 Dec 21 09:56 toolaut—————對應auth
而針對auth,da等的配置文件都存放於:
vendor/mediatek/proprietary/scripts/secure_chip_tools/settings/
drwxr-xr-x 6 keli cdgroup 4096 Dec 19 11:30 ./
drwxr-xr-x 8 keli cdgroup 4096 Dec 20 15:41 ../
drwxr-xr-x 2 keli cdgroup 4096 Dec 19 11:30 pbp/
drwxr-xr-x 2 keli cdgroup 4096 Dec 21 09:50 resignda/————對應DA
drwxr-xr-x 2 keli cdgroup 4096 Dec 20 15:13 sctrlcert/————對應secrtfile
drwxr-xr-x 2 keli cdgroup 4096 Dec 21 09:50 toolauth/—————對應auth
DA的keys:
其中da_prvk.pem和epp_prvk.pem都是RSA2048格式
-rw-r--r-- 1 keli cdgroup 1679 Nov 28 17:11 da_prvk.pem
-rw-r--r-- 1 keli cdgroup 1679 Nov 28 17:11 epp_prvk.pem
-rw-r--r-- 1 keli cdgroup 451 Nov 3009:32 PUBKda_prvk.pem
其中da_prvk可以openssl生成一份,也可以直接使用root_prvk去 rename。
簽名DA_BR時,da_prvk.pem需要和auth中的DAA key匹配
簽名DA_PL時要和dakey.h中的key匹配
Note:epp_prvk.pem可使用與da_prvk.pem一樣的keys,epp_prvk,MTK說是爲了兼容以前框架所用。
在settings的配置文件中:
bbchips_pss.ini中有如下配置需要double check
然後將需要簽名的DA放在prebuilt/resignda/路徑下,以psspadding的方式去執行DA的簽名命令:
python resign_da.py prebuilt/resignda/newMTK_AllInOne_DA.bin ¥platform settings/resignda/bbchips_pss.ini all out/resignda/newMTK_DA.bin-resign
Efuse.xml的配置
Note:
Security 2.1 EFUSE燒錄的efuse.xml文件需要配置key-type位,key-type值有legacy和pss兩種,如果不配置,默認是legacy。值得注意的是,efuxe.xml需要聯繫MTK獲取,不要自行修改或者混用。
Note!!!:相同的一組SBC Key,key-type設置不同則生成的key hash也不同,因此燒入refuse後無法更正,請確保key-type的配置是否正確,如果不確定,可以與MTK ACS support確認。、
efuse.xml配置指導:
<?xml version="1.0" encoding="UTF-8" ?>
<flashtool-config version="2.0">
<general>
<chip-name>MT6779</chip-name> //平臺信息,對應項目的xml該項應該是匹配的,如果不匹配請確認xml來源
....
preloader_¥project.bin //在此preloader中校驗
...
<connection
type="BromUSB" //下載端口需要對應
...
<efuse>
<magic-key /*需要和efuse.h中定義的key匹配,注意倒敘
key1="f6e2b190"
key2="c9a8d573" />
/*
比如在code中的值如下
4#defineEFUSE_BLOW_KEY1 0x90b1e2f6
5#defineEFUSE_BLOW_KEY2 0x73d5a8c9
則efuse.xml中必須爲
key1="f6e2b190"
key2="c9a8d573"/>
*/
...
Disable_DBGPORT_LOCK="false"
Enable_SW_JTAG_CON="true"
Enable_ACC="false"
Enable_ACK="false"
Enable_SLA="true"//校驗AUTH文件的SLA
Enable_DAA="true"//校驗DA,項目初調試,可以先開啓DA,驗證DA通過後,再開啓AUTH驗證,這樣有助於定位問題
Enable_SBC="true"//校驗SBC
Disable_JTAG="false" />
<sbc-pub-key>//security2.1preloader默認是cert_chain格式,對應此項配置是key_type爲pss,pub-key-e必須設置爲010001,如不確定,向MTK諮詢
<key-type>pss</key-type>
<pub-key-e>010001</pub-key-e>
<pub-key-n>//security 2.1,此處的keys值可以直接從root中獲取,這裏不需要配置
</pub-key-n>
</sbc-pub-key>
<common-lock
com_ctrl_lock="false" //ctrl定製位鎖
usb_id_lock="false"/>
<secure-lock
sec_msc_lock="false"
sec_attr_lock="false"
ackey_lock="false"
sbc_pubk_hash_lock="false" /> //efuse hash的鎖,字面理解,但有個疑問,既然是EFUSE,應該寫入後熔斷,爲什麼需要上鎖呢?脫了褲子放個屁?
...
<sec_msc
md1_sbc_en="true"/> //區別於SecureBoot和AVB,這是MTK自己的modem簽名驗證功能
<c_ctrlm
disable_self_blow="false" /> //是否允許自燒寫
Auth生成:
Efuse燒寫了DAA or SLA,在下載的時候,需要用到auth file和scertfile,需要使用python腳本生成
Auth key配置:
Auth的keys
Auth的配置改動和MTK文檔不同,auth處請詳細參考該文檔
da_pubk.pem*//da_prvk和sla_prvk:這裏找了下邏輯,最終會根據prvk去拿pubk,所以可以直接用公鑰,而prvk可以保存起來不開放。
epp_prvk.pem*//epp_prvk:和MTK確認過,是爲了兼容之前的架構,可以不管,不會用到
root_pubk.pem
sla_pubk.pem //這個由OEM同一使用,開發一般只能拿到pubk
在auth的settings配置中,先確定toolath_key.ini中
確認rootkey的路徑是否OK
確認tooauth_gfh_config_pss.ini配置:
注意:
此處於上圖差異部分:
sla_pad_type與開啓SLA功能客製化的sla_challenge.dll 使用的pad type一直,daa_pad_type_pad_type與sign DA使用的padding type一致
Auth生成命令:
python toolauth.py -i settings/toolauth/toolauth_key.ini -gsettings/toolauth/toolauth_gfh_config_pss.ini out/toolauth/authXX.auth
結束檢查:
一切配置OK,請做最後的double confirm(針對MTK6799,6767,6758,6739等新平臺)
檢查SBC_PUBK_HASH
Key config:
preloader/custom/$peoject/security/chip_config/s/key/pl_key.ini
檢查自己的keys:
確定該路徑下的prvk是自己本次配置的,如果不是,請覆蓋root_prvk.pem
對於efuseself-blow,這些SBC_PUBK_HASH是由這裏去獲取,而不是配置在input.xml中
以上是security2.1 secure boot完全配置方案
Note:
在刷機前要確定efuse.img是否選中,並且分區中是否有對應的分區表信息
Effuse手機,需要電池電壓高於3.7V(可以參考自己項目電池電量)
並且開機後,開機過程不要關機,確保efuse流程能正常運行完成
5. 共基線secure boot開發策略
在共基線開發多個項目時,由於secure 2.1方案存在證書和密鑰的路徑是在平臺路徑下,沒有區分項目,所以這塊的策略需要處理:
1. vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/$platrm/src/security/inc/sec_efuse.h
該文件中定義了兩個magic key,會在efuse.xml中對magickey進行匹配校驗,所以對於這裏的key需要做項目區分,當然也可以用同一個keys,這樣efuse.xml中magickey也保持相同
2. ~/vendor/mediatek/proprietary/custom/$project/security/cert_config下存放了cert和keys
共基線策略:
drwxr-xr-x 4 keli cdgroup 4096 Dec 27 16:32 XXX1/———新添加的項目X1文件夾,其中存放cert1和cert2_key
drwxr-xr-x 2 keli cdgroup 4096 Dec 21 11:07 cert1/——通用的,可保持默認
drwxr-xr-x 2 keli cdgroup 4096 Dec 21 11:07 cert2_key/
-rw-r--r-- 1 keli cdgroup 311 Dec 2111:07 img_list.txt——簽名鏡像信息,設置簽名鏡像列表
-rw-r--r-- 1 keli cdgroup 886 Dec 2111:07 img_ver.txt——版本信息,確定每個簽名版本的一些配置情況,使用默認即可
drwxr-xr-x 4 keli cdgroup 4096 Dec 27 17:21 XXX2/-------新添加的項目X2文件夾,其中存放cert1和cert2_key
以上項目名注意與環境變量中的項目名對應
3. 簽名腳本
Cert_config是在簽名的時候調用,所以也需要修改簽名時候獲取的路徑:
--- a/sign-image_v2/SignFlow.py
+++ b/sign-image_v2/SignFlow.py
@@ -41,9 +41,9 @@ def setPath():
if (project =="X1"):
cert1_dir = cert_dir+"/XXX1/cert1/"
cert2_key_dir = cert_dir+"/XXX1/cert2_key/"
elif (project =="X2"):
cert1_dir = cert_dir+"/XXX2/cert1/"
cert2_key_dir =cert_dir+"/XXX2/cert2_key/"
else:
cert1_dir =cert_dir+"/cert1/"
cert2_key_dir =cert_dir+"/cert2_key/"
6. 驗證結果
Efuse後,需要驗證手機是否已經置於efuse狀態,驗證方法如下:
1. 開機在lk界面時:左下角會顯示logo:
Efuse blow:seccuesful
2. 開完成後,讀取出efuse.img,查看裏面內容,開頭出現大量aaaaa內容即成功,如下:
怎麼導出efuse分區:
在adbshell下/dev/block/platform/bootable/by-name/下,查找efuse對應的分區號:e.g. mmcblk0p17
然後remount後將分區導出
adb pull /dev/block/mmcblk0p17
然後查看分區數據:hd mmcblk0p17
00000000 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................|
*
00000200 1c 00 00 00 28 01 0000 ff 02 00 00 ff 02 00 00 |....(...........|
00000210 ff 02 00 00 ff 02 0000 29 01 00 00 00 00 00 00 |........).......|
00000220 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 |................|
*
00080000
@test
3. 將未簽名的鏡像刷入,手機無法開機,然後再將鏡像簽名刷入,可開機。說明已經efuse