Skip to main content

Signing & Enforcing Security

TODO

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.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
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 is 16

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.

integrated in to build.sh

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}
ArtifactExpectedResult
apusys.imgYY
boot-debug.imgYN 1
boot.imgYN 2
ccu.imgYY
connsys_bt.imgYY
connsys_gnss.imgYY
connsys_wifi.imgYY
dpm.imgYY
dtbo.imgYY
efuse.imgYY
gpueb.imgYY
gz.imgYY
init_boot.imgYN 3
lk.imgYY
logo.imgYY
mcf_ota.imgYN 4
mcf_ota_TK_MD_NLWCG_6878__R16MP5.imgYN 5
mcupm.imgYY
modem.imgYN 6
odm_dlkm.imgYN 7
pi_img.imgYY
preloader_emmc.imgYY
preloader.imgYY
preloader_raw.imgYY
preloader_ufs.imgYY
product.imgYN 8
scp.imgYY
spmfw.imgYY
sspm.imgYY
super_empty.imgNN
super.imgYN 9
system_dlkm.imgYN 10
system_ext.imgYN 11
system.imgYN 12
system_other.imgYN 13
tee.imgYY
userdata.imgNN
vbmeta.imgYN 14
vbmeta_system.imgYN 15
vbmeta_vendor.imgYN 16
vcp.imgYY
vendor_boot-debug.imgYN 17
vendor_boot.imgYN 18
vendor_dlkm.imgYN 19
vendor.imgYN 20
download_agent/DA_BR.binYN 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

  1. Output:

    =======builds/NEXT.MC03.20260130.U0/boot-debug.img=======
    ===gfh parsing===
    =====> Error:Authfile Signature Verification Failure
  2. Output:

    =======builds/NEXT.MC03.20260130.U0/boot.img=======
    ===gfh parsing===
    =====> Error:Authfile Signature Verification Failure
  3. Output:

    =======builds/NEXT.MC03.20260130.U0/init_boot.img=======
    Error: Unknown file type, header magic not found
  4. Output:

    =======builds/NEXT.MC03.20260130.U0/mcf_ota.img=======
    Error: Unknown file type, header magic not found
  5. Output:

    =======builds/NEXT.MC03.20260130.U0/mcf_ota_TK_MD_NLWCG_6878__R16MP5.img=======
    Error: Unknown file type, header magic not found
  6. 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
  7. Output:

    =======builds/NEXT.MC03.20260130.U0/odm_dlkm.img=======
    Error: Unknown file type, header magic not found
  8. Output:

    =======builds/NEXT.MC03.20260130.U0/product.img=======
    ===gfh parsing===
    =====> Error:Authfile Signature Verification Failure
  9. Output:

    =======builds/NEXT.MC03.20260130.U0/super.img=======
    ===gfh parsing===
    =====> Error:Authfile Signature Verification Failure
  10. Output:

    =======builds/NEXT.MC03.20260130.U0/system_dlkm.img=======
    Error: Unknown file type, header magic not found
  11. Output:

    =======builds/NEXT.MC03.20260130.U0/system_ext.img=======
    ===gfh parsing===
    =====> Error:Authfile Signature Verification Failure
  12. Output:

    =======builds/NEXT.MC03.20260130.U0/system.img=======
    ===gfh parsing===
    =====> Error:Authfile Signature Verification Failure
  13. Output:

    =======builds/NEXT.MC03.20260130.U0/system_other.img=======
    Error: Unknown file type, header magic not found
  14. Output:

    =======builds/NEXT.MC03.20260130.U0/vbmeta.img=======
    Error: Unknown file type, header magic not found
  15. Output:

    =======builds/NEXT.MC03.20260130.U0/vbmeta_system.img=======
    Error: Unknown file type, header magic not found
  16. Output:

    =======builds/NEXT.MC03.20260130.U0/vbmeta_vendor.img=======
    Error: Unknown file type, header magic not found
  17. Output:

    =======builds/NEXT.MC03.20260130.U0/vendor_boot-debug.img=======
    ===gfh parsing===
    =====> Error:Authfile Signature Verification Failure
  18. Output:

    =======builds/NEXT.MC03.20260130.U0/vendor_boot.img=======
    ===gfh parsing===
    =====> Error:Authfile Signature Verification Failure
  19. Output:

    =======builds/NEXT.MC03.20260130.U0/vendor_dlkm.img=======
    ===gfh parsing===
    =====> Error:Authfile Signature Verification Failure
  20. Output:

    =======builds/NEXT.MC03.20260130.U0/vendor.img=======
    ===gfh parsing===
    =====> Error:Authfile Signature Verification Failure
  21. Output:

    =======builds/NEXT.MC03.20260130.U0/download_agent/DA_BR.bin=======
    ERROR: DA verification not supported yet.