Signing & Enforcing Security
This article is a work in progress.
This article describes the process of preparing to configure on-device integrity and thus security-related policies, their enforcement, the blowing of the eFuse, and validation routines that establish whether the configuration, build and production end-result are successful.
The article is currently very specific to a particular Mediatek Dimensity 7300 (aka. mt6878), so please keep that in mind if you wish to exercise this against another SoC.
About Download & Boot Security
It seems that there is no direct link from BROM configuration that enforces boot security to the
phone's firmware (we call vendor) and operating system (we call system). Rather, it would
seem that Downloader Agent Authentication is used to allow for a sort of "pivoting".
Presumably, if the BROM configuration blocks an unauthenticated Downloader Agent from flashing
vendor and system, then an authenticated Downloader Agent is trusted to flash vendor and
system (and various other images to various other partitions).
This implies we need to keep the authentication file for the Downloader Agent private and secret, separately from keeping the other private keys and their public counterparts private and secret also. We establish the following three target groups, but before we do so, we can refer to devices themselves as being of a particular type:
- development devices are unsecured and insecure (no BROM configuration, no eFuse blown, etc.)
- production devices are secured and have their eFuse blown (ready for general consumption by the public
We should further note that a signed Downloader Agent does not provide this pivot in and by itself;
the Downloader Agent file is part of the build artifacts and distributed alongside the other build
artifacts (more precisely, DA_BR.bin lives in download_agent/ right next to flash.xml).
Group 1: Research & Development
Research & Development personnel will not be provided access to any of the private/public keys discussed here and elsewhere.
This means they require a pool of devices that do not enforce any BROM policy configuration and do not have their eFuse blown. They are by definition development devices.
Unless Research & Development needs to flash a production device, they also do not need access to
the Downloader Agent Authentication file (da.auth) discussed below.
Group 2: Release Engineering
Release Engineering personnel is provided access to the private/public keys discussed here and elsewhere, and become required in releasing anything from development to production.
While authorized and capable of working with production devices, they need development devices as well to support the Research & Development team, and participate in Research & Development.
At least before the production run is executed, Release Engineering will need to be able to develop, check and double-check, document and have reviewed process documentation such as this article.
Group 3: Product Development & Support
Product Development & Support personnel deals of course with early project setup and device returns throughout the lifecycle of a particular SKU.
This means they will need to be provided access to a signed Downloader Agent (already included in
the distributed build) as well as the associated Downloader Agent Authentication file (da.auth
discussed below).
Step 0: Spartans, prepare for glory
All of the following steps are executed on the vendor/ side of the project build hierarchy.
cd vendor/
Step 1: Preloader & eFuse
In vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/k6878v1_64/k6878v1_64.mk,
ensure the following settings are set according to the following, and export them;
MTK_SECURITY_SW_SUPPORT=yes
MTK_SECURITY_ANTI_ROLLBACK=yes
# alternative ATTR_SBOOT_ONLY_ENABLE_ON_SCHIP to depend on SBC_EN
MTK_SEC_BOOT=ATTR_SBOOT_ENABLE
# alternative ATTR_SUSBDL_ONLY_ENABLE_ON_SCHIP to depend on SBC_EN
MTK_SEC_USBDL=ATTR_SUSBDL_ENABLE
MTK_EFUSE_WRITER_SUPPORT=yes
MTK_EFUSE_WRITER_VFY_SUPPORT=yes
MTK_EFUSE_WRITER_RESERVE_CODESIZE=yes
The above alternative configuration values make the effectiveness of the configured setting depend
on SBC_EN (rather, the enabling of SBC).
vim vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/k6878v1_64/k6878v1_64.mk
See Review 3350
Step 2: Little Kernel
In vendor/mediatek/proprietary/bootable/bootloader/lk2/project/k6878v1_64.mk, ensure the
following settings are available;
MTK_SECURITY_SW_SUPPORT=yes
MTK_SECURITY_ANTI_ROLLBACK=yes
vim vendor/mediatek/proprietary/bootable/bootloader/lk2/project/k6878v1_64.mk
See Review 3351
Step 3: Kernel
In kernel/kernel_device_modules-6.1/arch/arm64/configs/mgk_64_k61_defconfig, ensure the
following setting is available;
CONFIG_MTK_SECURITY_SW_SUPPORT=m
vim kernel/kernel_device_modules-6.1/arch/arm64/configs/mgk_64_k61_defconfig
See Review 3352
In device/mediateksample/k6878v1_64/ko_order_table.csv, ensure the following setting is present:
sec.ko,/../kernel_device_modules-6.1/drivers/misc/mediatek/masp/sec.ko,ramdisk,Y,Y,user/userdebug/eng
vim device/mediateksample/k6878v1_64/ko_order_table.csv
Step 4: Download Agent
In
vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6878/flash/make_script/mode/DA_BR.mak,
ensure the following settings are available;
C_OPTION += -DDA_ENABLE_SECURITY=1
C_OPTION += -DDA_ENABLE_ANTI_ROLLBACK=1
vim \
vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6878/flash/make_script/mode/DA_BR.mak
See Review 3353
Step 5: Generate Public and Private Keys
Generate a "root" and "image" public/private key pair (documented as step 1 through 3):
cd vendor/mediatek/proprietary/scripts/sign-image_v2/der_extractor/
openssl genrsa -out root_prvk.pem 2048
openssl rsa -in root_prvk.pem -pubout -out root_pubk.pem
openssl genrsa -out img_prvk.pem 2048
openssl rsa -in img_prvk.pem -pubout -out img_pubk.pem
See Review 3354
Step 6: Convert to DER format
Convert from PEM format to DER format using the provided script (documented as step 4 and 5):
python pem_to_der.py root_prvk.pem root_prvk.der
python pem_to_der.py root_pubk.pem root_pubk.der
python pem_to_der.py img_prvk.pem img_prvk.der
python pem_to_der.py img_pubk.pem img_pubk.der
See Review 3355
Step 7: Generate oemkey.h
Generate oemkey.h:
./der_extractor \
root_pubk.der \
oemkey.h \
ANDROID_SBC
Step 8: Correct oemkey.h
Edit oemkey.h and correct OEM_PUBK_SZ from its set value 259 to 256:
sed -i -e 's/OEM_PUBK_SZ 259/OEM_PUBK_SZ 256/g' oemkey.h
See Review 3356
Step 9: Copy oemkey.h to dakey.h
Re-use oemkey.h as dakey.h:
sed -e 's/OEM/DA/g' -e 's/DA_PUBK /DA_PUBK /g' oemkey.h > dakey.h
See Review 3357
Step 10: Distribute OEMKEY
Navigate back to the vendor/ root:
cd -
Replace the values of OEM_PUBK definitions in the following locations:
vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/k6878v1_64/inc/oemkey.hvendor/mediatek/proprietary/bootable/bootloader/lk2/target/k6878v1_64/include/oemkey.hvendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6878/flash/custom/oemkey.h
vim \
vendor/mediatek/proprietary/scripts/sign-image_v2/der_extractor/oemkey.h \
vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/k6878v1_64/inc/oemkey.h \
vendor/mediatek/proprietary/bootable/bootloader/lk2/target/k6878v1_64/include/oemkey.h \
vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6878/flash/custom/oemkey.h
The number of lines to copy from the original oemkey.h file is 16 lines.
However, the number of lines spent on define OEM_PUBK varies per target. Work your way forwards
first and yank-paste everywhere, then work your way backwoards to remove the obsolete definitions.
See Review 3358 and Review 3359
Step 11: Distribute dakey.h
Copy vendor/mediatek/proprietary/scripts/sign-image_v2/der_extractor/dakey.h to
vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/k6878v1_64/inc/dakey.h:
cd vendor/mediatek/proprietary/
cp scripts/sign-image_v2/der_extractor/dakey.h \
bootable/bootloader/preloader/custom/k6878v1_64/inc/dakey.h
cd -
See Review 3360
Step 12: Deploy Image Certificates
Regenerate cert1 and cert2 throughout:
cd vendor/mediatek/proprietary/scripts/
python2.7 \
sign-image_v2/img_key_deploy.py \
mt6878 \
cert1_key_path=sign-image_v2/der_extractor/root_prvk.pem \
cert2_key_path=sign-image_v2/der_extractor/img_prvk.pem \
root_key_padding=pss
cd -
See Review 3361
Step 13: Distribute img_prvk.pem and root_prvk.pem
Ensure preloader and download agent have the correct keys as well:
cd vendor/mediatek/proprietary/
cp \
scripts/sign-image_v2/der_extractor/{img,root}_prvk.pem \
bootable/bootloader/preloader/custom/k6878v1_64/security/chip_config/s/key/
cp \
scripts/sign-image_v2/der_extractor/{img,root}_prvk.pem \
bootable/bootloader/preloader/custom/k6878v1_64/security/chip_config/s/key/rsa2048/
cp \
scripts/sign-image_v2/der_extractor/{img,root}_prvk.pem \
scripts/secure_chip_tools/custom_keys/.
cp \
scripts/sign-image_v2/der_extractor/root_prvk.pem \
scripts/secure_chip_tools/custom_keys/da_prvk.pem
cp \
scripts/sign-image_v2/der_extractor/root_prvk.pem \
scripts/secure_chip_tools/custom_keys/epp_prvk.pem
cp \
scripts/sign-image_v2/der_extractor/root_prvk.pem \
scripts/secure_chip_tools/custom_keys/sla_prvk.pem
cd -
See Review 3362 and Review 3363
Step 14: Adjust Project Configuration
Enable MTK_EFUSE_WRITER_SUPPORT in device/mediateksample/k6878v1_64/ProjectConfig.mk
vim device/mediateksample/k6878v1_64/ProjectConfig.mk
See Review 3364
Step 15: Configure eFuse input.xml
Take the modulus and exponent of root_pubk.der, put the results in to
vendor/mediatek/proprietary/custom/k6878v1_64/security/efuse/input.xml, enable SBC and DAA,
disable JTAG and set the storage type to UFS:
cd vendor/mediatek/proprietary/
modulus=$(openssl asn1parse \
-inform DER \
-in scripts/sign-image_v2/der_extractor/root_pubk.der \
-i \
-strparse 19 | \
awk -F':' '{print $4}' | \
grep -E '^[0-9A-F]{7}')
exponent=$(openssl asn1parse \
-inform DER \
-in scripts/sign-image_v2/der_extractor/root_pubk.der \
-i \
-strparse 19 | \
awk -F':' '{print $4}' | \
grep -E '^[0-1]{6}$')
sed -i \
-e 's@<storage-type>EMMC</storage-type>@<storage-type>UFS</storage-type>@g' \
-e 's@Enable_DAA="false"@Enable_DAA="true"@g' \
-e 's@Enable_SBC="false"@Enable_SBC="true"@g' \
-e 's@Disable_JTAG="false"@Disable_JTAG="true"@g' \
-e "s@<pub-key-e></pub-key-e>@<pub-key-e>${exponent}</pub-key-e>@g" \
-e "s@<pub-key-n></pub-key-n>@<pub-key-n>${modulus}</pub-key-n>@g" \
custom/k6878v1_64/security/efuse/input.xml
cd -
See Review 3365
Step 16: Disable Self-Blowing
Optionally, disable self-blowing capabilities by changing TRUE to FALSE for
param.enable_self_blow:
vim \
vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6878/src/drivers/platform.c \
+2026
See Review 3366
Step 17: Establish eFuse "Magic" Keys
Decide on two eFuse "magic" keys, and put them in to
vendor/mediatek/proprietary/custom/k6878v1_64/security/efuse/input.xml as well as
vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6878/src/security/inc/sec_efuse.h:
key1=$(head -c 500 /dev/urandom | tr -dc 0-9A-F | head -c8)
key2=$(head -c 500 /dev/urandom | tr -dc 0-9A-F | head -c8)
key1r="${key1:6:2}${key1:4:2}${key1:2:2}${key1:0:2}"
key2r="${key2:6:2}${key2:4:2}${key2:2:2}${key2:0:2}"
cd vendor/mediatek/proprietary/
sed -r -i \
-e "s/key1=\"[0-9A-F]{8}\"/key1=\"${key1}\"/g" \
-e "s/key2=\"[0-9A-F]{8}\"/key2=\"${key2}\"/g" \
custom/k6878v1_64/security/efuse/input.xml
sed -r -i \
-e "s/^#define EFUSE_BLOW_KEY1(\s+).*$/#define EFUSE_BLOW_KEY1\10x${key1r}/g" \
-e "s/^#define EFUSE_BLOW_KEY2(\s+).*$/#define EFUSE_BLOW_KEY2\10x${key2r}/g" \
bootable/bootloader/preloader/platform/mt6878/src/security/inc/sec_efuse.h
cd -
See Review 3367
Step 18: Prepare DA Auth File (1)
Set <da_structure_version>0x1</da_structure_version> in
vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6878/flash/make_script/chip_info.xml.
It will look similar to the following:
<?xml version="1.0" encoding="UTF-8" ?>
<chip>
<hw_code>0x1375</hw_code>
<hw_sub_code>0x8A00</hw_sub_code>
<hw_version>0xCA00</hw_version>
<sw_version>0x0000</sw_version>
<feature_set>0x0</feature_set>
<sram_code_start>0x2000000</sram_code_start>
<dram_code_start>0x40000000</dram_code_start>
<da_structure_version>0x1</da_structure_version>
</chip>
vim vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt6878/flash/make_script/chip_info.xml
See Review 3368
Step 19: Prepare DA Auth File (2)
Supply a device specific section in
vendor/mediatek/proprietary/scripts/secure_chip_tools/settings/Legacy/da/bbchips_pss.ini. It will
look similar to the following (some of the information is available in chip_info.xml from the
previous step):
[mt6878]
hw_code = 0x1375
hw_sub_code = 0x8A00
hw_ver = 0xCA00
sw_ver = 0x0
da_ver = 0x1
load_region0_sigtype = epp
load_region0_sigpad = pss
load_region0_key = custom_keys/epp_prvk.pem
load_region1_sigtype = da
load_region1_sigpad = pss
load_region1_key = custom_keys/da_prvk.pem
load_region2_sigtype = da
load_region2_sigpad = pss
load_region2_key = custom_keys/da_prvk.pem
vim vendor/mediatek/proprietary/scripts/secure_chip_tools/settings/Legacy/da/bbchips_pss.ini
See Review 3369
Step 20: Generate DA Auth File
Generate the DA authentication file:
cd vendor/mediatek/proprietary/scripts/secure_chip_tools/
python2.7 \
MTK/toolauth.py \
-i settings/Legacy/authfile/toolauth_key.ini \
-g settings/Legacy/authfile/toolauth_gfh_config_pss.ini \
out/toolauth/da.auth
cd -
See Review 3370
Step 21: Take a Full Build
Take a full build (for the vendor/ part). On a properly resourced build system, this should take
no more than 2 hours across the three available build variants (eng/user/userdebug).
cd ..
time ./build.sh --vendor --no-merge
cd -
Step 22: Sign Downloader Agents
Sign the downloader agents.
See Review 3371 for tooling fixes required.
As it seems that at least each build variant yields a different DA_BR.bin result, signing each of
the variant's separately is most properly integrated in the build script itself.
cd vendor/mediatek/proprietary/scripts/secure_chip_tools/
for variant in eng user userdebug; do
cp -af ../../../../../${variant}/out/target/product/k6878v1_64/download_agent/DA_BR.bin prebuilt/da/DA_BR_${variant}.bin
python2.7 sec_master.py \
-t da \
-in prebuilt/da/DA_BR_${variant}.bin \
-out out/pk/DA_BR_${variant}.bin \
-plat mt6878 \
-da_cfg settings/Legacy/da/bbchips_pss.ini
cp -af \
out/pk/DA_BR_${variant}.bin \
../../../../../${variant}/out/target/product/k6878v1_64/download_agent/DA_BR.bin
cd -
Step 23: Verifying Build Artifacts
For each of the build artifacts listed below, we execute the following command:
python2.7 \
vendor/vendor/mediatek/proprietary/scripts/sign-image_v2/sign.py \
type=verify \
pubk=vendor/vendor/mediatek/proprietary/scripts/sign-image_v2/der_extractor/root_pubk.pem \
ver=0 \
root_key_ver=0 \
path={path}
| Artifact | Expected | Result |
|---|---|---|
apusys.img | Y | Y |
boot-debug.img | Y | N 1 |
boot.img | Y | N 2 |
ccu.img | Y | Y |
connsys_bt.img | Y | Y |
connsys_gnss.img | Y | Y |
connsys_wifi.img | Y | Y |
dpm.img | Y | Y |
dtbo.img | Y | Y |
efuse.img | Y | Y |
gpueb.img | Y | Y |
gz.img | Y | Y |
init_boot.img | Y | N 3 |
lk.img | Y | Y |
logo.img | Y | Y |
mcf_ota.img | Y | N 4 |
mcf_ota_TK_MD_NLWCG_6878__R16MP5.img | Y | N 5 |
mcupm.img | Y | Y |
modem.img | Y | N 6 |
odm_dlkm.img | Y | N 7 |
pi_img.img | Y | Y |
preloader_emmc.img | Y | Y |
preloader.img | Y | Y |
preloader_raw.img | Y | Y |
preloader_ufs.img | Y | Y |
product.img | Y | N 8 |
scp.img | Y | Y |
spmfw.img | Y | Y |
sspm.img | Y | Y |
super_empty.img | N | N |
super.img | Y | N 9 |
system_dlkm.img | Y | N 10 |
system_ext.img | Y | N 11 |
system.img | Y | N 12 |
system_other.img | Y | N 13 |
tee.img | Y | Y |
userdata.img | N | N |
vbmeta.img | Y | N 14 |
vbmeta_system.img | Y | N 15 |
vbmeta_vendor.img | Y | N 16 |
vcp.img | Y | Y |
vendor_boot-debug.img | Y | N 17 |
vendor_boot.img | Y | N 18 |
vendor_dlkm.img | Y | N 19 |
vendor.img | Y | N 20 |
download_agent/DA_BR.bin | Y | N 21 |
Step 24: Read eFuse
Execute the following command:
LD_LIBRARY_PATH=./:./lib \
./SPFlashTool \
-c read-efuse \
-f ~/Downloads/NEXT.MC03/NEXT.MC03.20260123.D0/download_agent/flash.xml \
--file ~/efuse-read-NEXT.MC03.20260123.D0.txt
Footnotes
-
Output:
↩=======builds/NEXT.MC03.20260130.U0/boot-debug.img=======
===gfh parsing===
=====> Error:Authfile Signature Verification Failure -
Output:
↩=======builds/NEXT.MC03.20260130.U0/boot.img=======
===gfh parsing===
=====> Error:Authfile Signature Verification Failure -
Output:
↩=======builds/NEXT.MC03.20260130.U0/init_boot.img=======
Error: Unknown file type, header magic not found -
Output:
↩=======builds/NEXT.MC03.20260130.U0/mcf_ota.img=======
Error: Unknown file type, header magic not found -
Output:
↩=======builds/NEXT.MC03.20260130.U0/mcf_ota_TK_MD_NLWCG_6878__R16MP5.img=======
Error: Unknown file type, header magic not found -
Output:
↩=======builds/NEXT.MC03.20260130.U0/modem.img=======
-------md1rom-------
md_img =temp_md1img
md_img =temp_md1img
GFH found (MAUI_CODE_KEY), 0x604
Error:cert1md missing pubk hash -
Output:
↩=======builds/NEXT.MC03.20260130.U0/odm_dlkm.img=======
Error: Unknown file type, header magic not found -
Output:
↩=======builds/NEXT.MC03.20260130.U0/product.img=======
===gfh parsing===
=====> Error:Authfile Signature Verification Failure -
Output:
↩=======builds/NEXT.MC03.20260130.U0/super.img=======
===gfh parsing===
=====> Error:Authfile Signature Verification Failure -
Output:
↩=======builds/NEXT.MC03.20260130.U0/system_dlkm.img=======
Error: Unknown file type, header magic not found -
Output:
↩=======builds/NEXT.MC03.20260130.U0/system_ext.img=======
===gfh parsing===
=====> Error:Authfile Signature Verification Failure -
Output:
↩=======builds/NEXT.MC03.20260130.U0/system.img=======
===gfh parsing===
=====> Error:Authfile Signature Verification Failure -
Output:
↩=======builds/NEXT.MC03.20260130.U0/system_other.img=======
Error: Unknown file type, header magic not found -
Output:
↩=======builds/NEXT.MC03.20260130.U0/vbmeta.img=======
Error: Unknown file type, header magic not found -
Output:
↩=======builds/NEXT.MC03.20260130.U0/vbmeta_system.img=======
Error: Unknown file type, header magic not found -
Output:
↩=======builds/NEXT.MC03.20260130.U0/vbmeta_vendor.img=======
Error: Unknown file type, header magic not found -
Output:
↩=======builds/NEXT.MC03.20260130.U0/vendor_boot-debug.img=======
===gfh parsing===
=====> Error:Authfile Signature Verification Failure -
Output:
↩=======builds/NEXT.MC03.20260130.U0/vendor_boot.img=======
===gfh parsing===
=====> Error:Authfile Signature Verification Failure -
Output:
↩=======builds/NEXT.MC03.20260130.U0/vendor_dlkm.img=======
===gfh parsing===
=====> Error:Authfile Signature Verification Failure -
Output:
↩=======builds/NEXT.MC03.20260130.U0/vendor.img=======
===gfh parsing===
=====> Error:Authfile Signature Verification Failure -
Output:
↩=======builds/NEXT.MC03.20260130.U0/download_agent/DA_BR.bin=======
ERROR: DA verification not supported yet.