MTK Secure Boot 2.1详细配置方案-终极版

 

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匹配

Noteepp_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配置指导:

 

 

   MT6779 //平台信息,对应项目的xml该项应该是匹配的,如果不匹配请确认xml来源

....

        preloader_¥project.bin //在此preloader中校验

...

   

      type="BromUSB" //下载端口需要对应

...

   

      需要和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" />

      //security2.1preloader默认是cert_chain格式,对应此项配置是key_type为pss,pub-key-e必须设置为010001,如不确定,向MTK咨询

           pss

        010001

        //security 2.1,此处的keys值可以直接从root中获取,这里不需要配置

       

     

 

     

        com_ctrl_lock="false"  //ctrl定制位锁

        usb_id_lock="false"/>

     

       sec_msc_lock="false"

       sec_attr_lock="false"

        ackey_lock="false"

       sbc_pubk_hash_lock="false" /> //efuse hash的锁,字面理解,但有个疑问,既然是EFUSE,应该写入后熔断,为什么需要上锁呢?脱了裤子放个屁?

...

     

        md1_sbc_en="true"/>  //区别于SecureBoot和AVB,这是MTK自己的modem签名验证功能

 

     

       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文件夹,其中存放cert1cert2_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文件夹,其中存放cert1cert2_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

你可能感兴趣的:(Security,System)