rk3568安全啟動功能實踐

????????本文主要講述筆者在rk3568芯片上開發安全啟動功能實踐的流程。其中主要參考瑞芯微官方文檔《Rockchip_Developer_Guide_Secure_Boot_for_UBoot_Next_Dev_CN.pdf》。文檔中描述邏輯不是很清晰而且和當前瑞芯微的sdk中安全啟動的流程匹配度不高。本文就不再對瑞芯微官方文檔的內容進行贅述,讀者可以先查看官方文件后再閱讀本文章。

? ? ? ??所謂的安全驗證引導流程分為安全性校驗與完整性校驗。安全性校驗是加密公鑰的校驗,流程為從安全存儲(OTP & efuse)中讀取公鑰 hash,與計算的公鑰 hash 對比,是否一致,然后公鑰用于解密固件hash。完整性校驗為校驗固件的完整性,流程為從存儲里加載固件,計算固件的hash與解密出來的hash對比是否一致。

1、使用什么方案?

????????Linux 系統中,提供了新舊2種Secure Boot方案,FIT和AVB方案,效果是一樣的,兩種方案不可混用,各個芯片具體選用那種方案,請參考產品版本。

? 從上面的圖中可知RK356X kernel校驗方式為FIT,安全分區為OTP。AVB和FIT的差異以及EFUSE和OTP的差異在瑞芯微官方文檔中有詳細描述這里不再贅述,只是希望讀者不要使用錯誤的方案。在配置時設置RK_SECUREBOOT_FIT=y ,不要配置RK_SECUREBOOT_AVB=y,因為rk3568芯片不支持AVB方案。

????????FIT(flattened image tree)是U-Boot?持的?種新固件類型的引導?案,?持任意多個image打包和校驗。FIT使?its(image source file)?件描述image信息,最后通過mkimage?具?成itb(flattened image tree blob)鏡像。its?件使?DTS的語法規則,?常靈活,可以直接使?libfdt 庫和相關?具。同時自帶一套全新的安全檢驗方式。

2、對uboot進行簽名

2.1、生成密鑰對

? ? ? ? 在對鏡像進行簽名之前,需要生成秘鑰對,作為對進行簽名的密鑰對。

????????U-Boot工程下執行如下三條命令可以生成簽名用的RSA密鑰對。通常情況下只需要生成一次,此后都用這對密鑰簽名和驗證固件,請妥善保管。

????????第一步:放key的目錄:keys

????????mkdir -p keys

????????第二步:使用RK的"rk_sign_tool"工具生成RSA2048的私鑰privateKey.pem和publicKey.pem,分別更名存放為:keys/dev.key和keys/dev.pubkey。命令為:

????????../rkbin/tools/rk_sign_tool kk --bits 2048 --out .

????????ln -s privateKey.pem keys/dev.key

????????ln -s publicKey.pem keys/dev.pubkey

????????第三步:使用-x509和私鑰生成一個自簽名證書:keys/dev.crt (效果本質等同于公鑰)

????????openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt

注意:上述的"keys"、"dev.key"、"dev.crt" 、"dev.pubkey"名字都不可變。因為這些名字已經在its

文件中靜態定義,如果改變則會打包失敗。

? ? ? ? 當然上面的步驟可以通過 build.sh security-createkeys命令來實現。

2.2、uboot配置

????????U-Boot的defconfig打開如下配置:

????????CONFIG_FIT_SIGNATURE=y

????????CONFIG_SPL_FIT_SIGNATURE=y

2.3、buildroot的配置

????????在瑞芯微sdk目錄下執行 make menuconfig->Security feature (secureboot, encryption, verity, etc.)? 來進行安全啟動相關配置的配置,配置了這些內容后,編譯SDK時會自動對uboot和kernel進行簽名。

? ? ? ? 如果想這些配置一開始就生效,可以在 SDK所在目錄的device/rockchip/rk3566_rk3568/rockchip_rk3568_evb1_ddr4_v10_defconfig 中添加fit相關的配置(rockchip_rk3568_evb1_ddr4_v10_defconfig 是筆者當前系統使用的配置,讀者需要根據自己編譯SDK時選擇的配置項修改對應的配置文件):

RK_UBOOT_SPL=y

RK_SECURITY=y

#

# Security check method (system-verity) needs squashfs rootfs type

#

RK_SECUREBOOT_METHOD="fit"

RK_SECUREBOOT_FIT=y

# RK_SECUREBOOT_AVB is not set

RK_SECURITY_OPTEE_STORAGE="rpmb"

RK_SECURITY_OPTEE_STORAGE_RPMB=y

# RK_SECURITY_OPTEE_STORAGE_SECURITY is not set

RK_SECURITY_CHECK_METHOD="base"

RK_SECURITY_CHECK_BASE=y

# RK_SECURITY_CHECK_SYSTEM_ENCRYPTION is not set

# RK_SECURITY_BURN_KEY is not set

3、對kernle進行簽名

????????在kernel內核配置文件rockchip_linux_defconfig文件中添加如下配置:

CONFIG_BLK_DEV_DM=y

CONFIG_DM_CRYPT=y

CONFIG_BLK_DEV_CRYPTOLOOP=y

CONFIG_DM_VERITY=y

????????將optee設備樹配置信息添加到rk3568.dtsi設備樹中

optee: optee {

????????compatible = "linaro,optee-tz";

????????method = "smc";

????????status = "okay";

};

????????內核開啟CONFIG_DM_VERITY=y的情況下,parameter-buildroot-fit.txt分區配置腳本中GROW_ALIGN: 1必須設置為1.具體可以查看SDK中的check-grow-align.sh 腳本,該腳本存在如下程序進行檢查:

# DM_VERITY存在且非空并并且GROW_ALIGN_VAL值為1,則exit 0

if [ "$DM_VERITY" -a "$GROW_ALIGN_VAL" = "1" ]; then

????????# DM verity + grow align

????????exit 0

fi

? ? ? ? 不配置的話,編譯時也會報錯提醒,根據提示信息修改即可。感興趣的同學可以通讀這個腳本。

4、驗證

????????注意,我們還沒有燒錄公鑰的hash值到OTP區。執行SDK的全編譯,將編譯后的固件燒錄到設備中。公鑰hash是否燒寫,只會影響Maskrom是否校驗loader,且燒錄后,無法撤銷。loader驗證uboot以及后續驗證流程還是一致的。因此,調試階段建議先不用burn-key-hash。

進行驗證,關鍵打印信息如下:
Trying fit image at 0x4000 sector
## Verified-boot: 0
sha256,rsa2048:dev## Verified-boot: 0
+?
## Checking atf-1 0x00040000 (gzip @0x00240000) ... sha256(ee9d731c06...) + sha256(b5946ac63d...) + OK
## Checking uboot 0x00a00000 (gzip @0x00c00000) ... sha256(49f841525c...) + sha256(30f02600a8...) + OK
## Checking fdt 0x00b53b50 ... sha256(f133b1d7de...) + OK
## Checking atf-2 0xfdcc1000 ... sha256(b8dca786b4...) + OK
## Checking atf-3 0x0006b000 ... sha256(2f91089eb7...) + OK
## Checking atf-4 0xfdcce000 ... sha256(86ef885748...) + OK
## Checking atf-5 0xfdcd0000 ... sha256(0b2b146c60...) + OK
## Checking atf-6 0x00069000 ... sha256(a9a1e63bef...) + OK
## Checking optee 0x08400000 (gzip @0x08600000) ... sha256(8f745f9f51...) + sha256(ac96eda7b3...) + OK

Jumping to U-Boot(0x00a00000) via ARM Trusted Firmware(0x00040000)
Total: 174.537/261.748 ms

......
## Loading kernel from FIT Image at 7925ce00 ...
? ?Using 'conf' configuration
optee api revision: 2.0
find partition misc ok?
find partition security_a error?
find partition security error?
TEEC: Waring: Could not find security partition
## Verified-boot: 0
? ?Verifying Hash Integrity ... sha256,rsa2048:dev+ OK
? ?Trying 'kernel' kernel subimage
? ? ?Description: ?unavailable
? ? ?Type: ? ? ? ? Kernel Image
? ? ?Compression: ?uncompressed
? ? ?Data Start: ? 0x7928be00
? ? ?Data Size: ? ?39238144 Bytes = 37.4 MiB
? ? ?Architecture: AArch64
? ? ?OS: ? ? ? ? ? Linux
? ? ?Load Address: 0x00280000
? ? ?Entry Point: ?0x00280000
? ? ?Hash algo: ? ?sha256
? ? ?Hash value: ? 6d75cfb71d410f9099cceddbb1b07a86528ba57a41f4fc67c2676e412fcf026e
? ?Verifying Hash Integrity ... sha256+ OK
## Loading fdt from FIT Image at 7925ce00 ...
? ?Using 'conf' configuration
? ?Trying 'fdt' fdt subimage
? ? ?Description: ?unavailable
? ? ?Type: ? ? ? ? Flat Device Tree
? ? ?Compression: ?uncompressed
? ? ?Data Start: ? 0x7925e000
? ? ?Data Size: ? ?187611 Bytes = 183.2 KiB
? ? ?Architecture: AArch64
? ? ?Load Address: 0x08300000
? ? ?Hash algo: ? ?sha256
? ? ?Hash value: ? acb7a59d28a3fb7893ab6a08dcad1bb17f404c0e4cca8d2fb13ed8a7614ee472
? ?Verifying Hash Integrity ... sha256+ OK
? ?Loading fdt from 0x08300000 to 0x08300000
? ?Booting using the fdt blob at 0x08300000
? ?Loading Kernel Image from 0x7928be00 to 0x00280000 ... OK
? ?kernel loaded at 0x00280000, end = 0x027eba00
? ?Using Device Tree in place at 0000000008300000, end 0000000008330cda
## reserved-memory:
? ramoops@110000: addr=110000 size=f0000
Adding bank: 0x00200000 - 0x08400000 (size: 0x08200000)
Adding bank: 0x09400000 - 0x80000000 (size: 0x76c00000)
board seed: Pseudo

......

== DO RELOCATE == Kernel from 0x00280000 to 0x00200000
Total: 882.698/929.496 ms

Starting kernel ...

將公鑰的哈希值燒錄到OTP區,需要設置將

# RK_SECURITY_BURN_KEY is not set修改為RK_SECURITY_BURN_KEY=y,這樣第一次上電時loader階段會自動將哈希值燒寫到OTP區。

5、sdk簽名流程分析

????????下面將分析下SDK中是如何來對uboot和kernel進行簽名的流程。主要在?check-security.sh腳本,mk-security.sh腳本分析.

? ? ? ? ?在?check-security.sh腳本中會根據配置是AVB方案還是FIT方案來檢查uboot和kernel的.config配置中上面對應的配置項是否進行了配置。

#!/bin/bash -e###################################################
RK_SCRIPTS_DIR="${RK_SCRIPTS_DIR:-$(dirname "$(realpath "$0")")}"
RK_SDK_DIR="${RK_SDK_DIR:-$RK_SCRIPTS_DIR/../../../..}"
UBOOT=$RK_SDK_DIR/u-boot
KERNEL=$RK_SDK_DIR/kernel
BUILDROOT=$RK_SDK_DIR/buildroot
RK_SIGN_TOOL=$RK_SDK_DIR/rkbin/tools/rk_sign_tool
###################################################ROOTFS_UPDATE_ENGINEBIN_CONFIGS=" \BR2_PACKAGE_RECOVERY \BR2_PACKAGE_RECOVERY_UPDATEENGINEBIN"ROOTFS_AB_FIXED_CONFIGS=" \$ROOTFS_UPDATE_ENGINEBIN_CONFIGS \BR2_PACKAGE_RECOVERY_BOOTCONTROL"UBOOT_FIT_FIXED_CONFIGS=" \CONFIG_FIT_SIGNATURE \CONFIG_SPL_FIT_SIGNATURE"UBOOT_AVB_FIXED_CONFIGS=" \CONFIG_ANDROID_AVB \CONFIG_AVB_LIBAVB \CONFIG_AVB_LIBAVB_AB \CONFIG_AVB_LIBAVB_ATX \CONFIG_AVB_LIBAVB_USER \CONFIG_RK_AVB_LIBAVB_USER \CONFIG_OPTEE_CLIENT \CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE \CONFIG_RK_AVB_LIBAVB_ENABLE_ATH_UNLOCK \CONFIG_OPTEE_V."# TODO:  CONFIG_ROCKCHIP_PRELOADER_PUB_KEYRAMBOOT_FIXED_CONFIG=" \BR2_PACKAGE_TEE_USER_APP \BR2_PACKAGE_LUKSMETA"#檢查keys是否存在
#可以使用 /build.sh createkeys 在rk3568_bsp/u-boot/keys 生成秘鑰對。
rk_security_check_keys()
{if [ ! -d "$UBOOT/keys" ]; thenecho "ERROR: No root keys(u-boot/keys) found in u-boot"echo "       Create it by ./build.sh security-createkeys or move your key to it"exit -1fiif echo "$1" | grep system ; thenif [ ! -f $UBOOT/keys/root_passwd ]; thenecho "ERROR: No root passwd(u-boot/keys/root_passwd) found in u-boot"echo "       echo your root key for sudo to u-boot/keys/root_passwd"echo "       some operations need supper user permission when create encrypt image"exit -1fiif [ "$1" = "system-encryption" ] && \[ ! -f $UBOOT/keys/system_enc_key ]; thenecho "ERROR: No enc key(u-boot/keys/system_enc_key) found in u-boot"echo "       Create it by ./build.sh security-createkeys or move your key to it"exit -1fifi
}BOOT_FIXED_CONFIGS=" \CONFIG_BLK_DEV_DM \CONFIG_DM_CRYPT \CONFIG_DM_VERITY"BOOT_FIXED_UNDER_6_1_CONFIG="CONFIG_BLK_DEV_CRYPTOLOOP"BOOT_OPTEE_FIXED_CONFIGS=" \CONFIG_TEE \CONFIG_OPTEE"#檢查uboot或者kernel的配置文件是否有對應的配置項
config_check()
{# 1. config 2. match itemecho debug-$1for i in $2doecho "look for $i"result=$(cat $1 | grep "${i}=y" -w || echo "No found")if [ "$result" = "No found" ]; thenecho -e "\e[41;1;37mSecurity: No found config ${i} in $1 \e[0m"echo "make sure your config include this list"echo "---------------------------------------"echo "$2" | xargs -n1echo "---------------------------------------"exit -1;fidonereturn 0
}rk_security_match_overlay()
{result=$(cat "$2" | grep "$3" || echo "No found")if [ "$result" = "No found" ]; thenecho -e "\e[41;1;37mSecurity: No found BR2_ROOTFS_OVERLAY+=\"board/rockchip/common/$3/\" in $1 config\e[0m"exit -1fi
}# 檢查system
rk_security_check_system()
{case $1 insystem-encryption|system-verity) rk_security_match_overlay system $2 security-system-overlay;;# base是不校驗system分區base) return 0;;*) exit -1;;esac
}# 檢查內核配置
rk_security_check_kernel_config()
{# RK_SECURITY=y# 開啟rk安全啟動配置情況下才作檢查[ ! -z "$RK_SECURITY" ] || return 0# 內核版本小于 6.1if [ $(echo "$RK_KERNEL_VERSION_RAW < 6.1" | bc) -eq 1 ]; thenBOOT_FIXED_CONFIGS="$BOOT_FIXED_CONFIGS $BOOT_FIXED_UNDER_6_1_CONFIG"ficase $1 insystem-encryption) BOOT_FIXED_CONFIGS="$BOOT_FIXED_CONFIGS $BOOT_OPTEE_FIXED_CONFIGS" ;& # fallthroughsystem-verity) config_check $2 "$BOOT_FIXED_CONFIGS" ;;base) return 0;;*) exit -1;;esac
}#檢查內核dts文件是否配置了optee 節點且enbable
rk_security_check_kernel_dts()
{test "$1" = "system-encryption" || return 0# ${ ## } 從變量開頭開始匹配最長的.(點),然后刪除if [ "${2##*.}" = "dtb" ]; thendtsfile=$(mktemp)# dtc 是 Linux 系統中用于編譯或反編譯設備樹(Device Tree)文件的工具# -I:Input formats 輸入文件格式# -O:Output formats 輸出文件格式# -o:Output file 輸出文件# 將輸入的dtb文件反編譯為dts輸出到dtsfile文件中dtc -q -I dtb -O dts -o $dtsfile $2elsedtsfile=$2fitmp_file=$(mktemp)#-P:啟用 Perl 兼容正則(支持更復雜的語法)。#-z:將文件視為單行(用 NULL 分隔),便于跨行匹配。#-o:僅輸出匹配內容#\t:轉義符#\s*{(\n|\w|-|;|=|<|>|\"|_|\s|,)*};#\s*:匹配0或多個空白字符(空格、制表符、換行等)#{:匹配左花括號。# (\n|\w|-|;|=|<|>|\"|_|\s|,)*:這是一個分組,包含多個選項,用|分隔,匹配任意次。這個部分意圖是匹配花括號內的內容,直到遇到結束的};#\n:換行符,允許跨行匹配。#\w:單詞字符(字母、數字、下劃線)。#-:直接匹配短橫線。#; = < > " _ \s ,:這些字符分別匹配。#使用*量詞可能會導致貪婪匹配,直到無法繼續為止,但由于后面有};作為結束,所以正則引擎會盡可能匹配到最近的};#};:匹配右花括號和分號,結束整個結構。if ! grep -Pzo "\toptee \s*{(\n|\w|-|;|=|<|>|\"|_|\s|,)*};" $dtsfile 1>$tmp_file 2>/dev/null; then# 匹配失敗則打印提示信息echo -e "\e[41;1;37mNo found optee node in dts\e[0m"echo "Please add: "echo "        optee: optee {"echo "                compatible = \"linaro,optee-tz\";"echo "                method = \"smc\";"echo "                status = \"okay\";"echo "        };"echo "To kernel dts"rm -f $tmp_file# 如果dtsfile是使用dtc反編譯出來的就將其刪除test "$2" = "$dtsfile" || rm $dtsfileexit -1fistatus=$(cat $tmp_file | grep -a status || true)if [ "$(echo $status | grep disabled)" ]; thenrm -f $tmp_filetest "$2" = "$dtsfile" || rm $dtsfileecho -e "\e[41;1;37mOptee Found, but disabled!!!\e[0m"exit -1firm -f $tmp_filetest "$2" = "$dtsfile" || rm $dtsfile
}# kernel內核配置檢查
rk_security_check_kernel()
{append=$1shiftcase $append in# linux內核配置和設備樹進行檢查:rk_security_check_kernel_config/dtsconfig|dts) rk_security_check_kernel_$append $@;;*) exit -1;;esac
}# 檢查ramboot
rk_security_check_ramboot()
{# 只有 RK_SECURITY_CHECK_METHOD為system-encryption情況下才作ramdisk的處理# 我們項目中RK_SECURITY_CHECK_METHOD="base",未使用該選項,可以不關注if [ "$1" != "system-encryption" ]; thenreturn 0fishiftif [ ! -f "$1" ]; thenecho -e "\e[41;1;37m$1 is not found\e[0m"exit -1fiecho "check ramdisk config"config_check $1 "$(echo $ROOTFS_UPDATE_ENGINEBIN_CONFIGS $RAMBOOT_FIXED_CONFIG)"rk_security_match_overlay ramboot $1 security-ramdisk-overlay
}# 檢查uboot
rk_security_check_uboot()
{METHOD=$1shift# fit配置下的uboot檢查if [ "$METHOD" = "fit" ]; then	config_check $1 "$UBOOT_FIT_FIXED_CONFIGS"else# avb情況config_check $1 "$UBOOT_AVB_FIXED_CONFIGS"fi
}rk_security_check_main()
{CHECK_LIST="keys kernel system uboot ramboot"for item in $CHECK_LISTdo# $1必須在 keys kernel system uboot ramboot 參數列表中if [ "$item" = "$1" ]; thenappend=$1shift# 調用對應的函數rk_security_check_keys/kernel/system/uboot/ramboot"rk_security_check_$append" $@fidone
}# -----------------------------------
# For SDK
# -----------------------------------# 根據鏡像來檢查uboot,kernel中的配置以及設備樹是否配置正確
rk_security_check_sdk()
{# $RK_SECURITY 非空則返回0,即如果要繼續執行下去,那么$RK_SECURITY的值應該為空 # RK_SECURITY=y[ ! -z "$RK_SECURITY" ] || return 0# 添加打印信息發現,$1的值應該為system# RK_SECURITY_CHECK_METHOD="base"case $1 inkeys) rk_security_check_main keys $RK_SECURITY_CHECK_METHOD ;;kernel)case $2 in#檢查kernle 的.config文件config) rk_security_check_main $@ $RK_SECURITY_CHECK_METHOD $RK_SDK_DIR/kernel/.config ;;dts) rk_security_check_main $@ $RK_SECURITY_CHECK_METHOD $RK_KERNEL_DTB ;;esac;;#檢查buildroot/output/.config文件system) rk_security_check_main system $RK_SECURITY_CHECK_METHOD $RK_SDK_DIR/buildroot/output/$RK_BUILDROOT_CFG/.config ;;ramboot) rk_security_check_main ramboot $RK_SECURITY_CHECK_METHOD $RK_SDK_DIR/buildroot/output/$RK_SECURITY_INITRD_CFG/.config ;;#檢查uboot的 .config文件uboot) rk_security_check_main uboot $RK_SECUREBOOT_METHOD $RK_SDK_DIR/u-boot/.config ;;esac
}# RK_SESSION="${RK_SESSION:-$(date +%F_%H-%M-%S)} 2025-04-15_10-58-34
# 如果 $RK_SESSION 存在且非空則執行 rk_security_check_sdk
if [ "$RK_SESSION" ]; thenrk_security_check_sdk $@
elserk_security_check_main $@
fi

mk-security.sh 腳本則是根據配置是AVB方案還是FIT方案來對boot,img進行簽名

#!/bin/bash -e# TODO: Almost product have enabled bl32.
# AVB Config should be set in AVB tools dir.
#     include keys / product id / efuse# For flash device, encryption-system remain space should be config
###################################################
RK_SCRIPTS_DIR="${RK_SCRIPTS_DIR:-$(dirname "$(realpath "$0")")}"
RK_SDK_DIR="${RK_SDK_DIR:-$RK_SCRIPTS_DIR/../../../..}"
UBOOT=$RK_SDK_DIR/u-boot
KERNEL=$RK_SDK_DIR/kernel
BUILDROOT=$RK_SDK_DIR/buildroot
RK_SIGN_TOOL=$RK_SDK_DIR/rkbin/tools/rk_sign_tool
RK_SIGN_INI=$RK_SDK_DIR/rkbin/tools/setting.ini
RK_AVB_TOOL_DIR=$RK_SDK_DIR/tools/linux/Linux_SecurityAVB/
RK_AVB_TOOL=$RK_AVB_TOOL_DIR/avb_user_tool.sh
###################################################
# 1 -> input misc	# 2 -> output misc
# 3 -> size		# 4 -> enc_keycheck_var_in_list()
{# 在$2中查找$1的值,成功返回0,否則返回1echo $2 | fgrep -wq $1 && return 0 || return 1
}assert_var_in_list()
{if ! check_var_in_list "$@" ; thenecho -e "\e[41;1;37m$1 not in List \"$2\" -- $(basename "${BASH_SOURCE[1]}") - ${FUNCNAME[1]}\e[0m"return 1fi
}rk_security_setup_misc()
{SRC=$1DST=$2size=$3buf=$4echo buf=$bufbig_end=$[size / 256]lit_end=$[size - (big_end * 256)]big_end=$(echo "ibase=10;obase=16;$big_end" | bc)lit_end=$(echo "ibase=10;obase=16;$lit_end" | bc)IMAGE_DIR="${RK_OUTDIR:-$UBOOT}/security"mkdir -p "$IMAGE_DIR"IMAGE="$IMAGE_DIR/misc-security.img"rm -rf "$IMAGE"ln -rsLf "$SRC" "$IMAGE_DIR/misc.img"dd if="$IMAGE_DIR/misc.img" of="$IMAGE" bs=1k count=10echo -en "\x$lit_end\x$big_end" >> "$IMAGE"echo -n "$buf" >> "$IMAGE"skip=$[10 * 1024 + size + 2]dd if="$IMAGE_DIR/misc.img" of="$IMAGE" seek=$skip skip=$skip bs=1ln -rsf "$IMAGE" "$DST"
}# 使用RK_SIGN_TOOL生成簽名loader,uboot的密鑰。
# 因為Loader到Uboot的校驗,由RK私有方案完成,所有使用rk_sign_tool工具進行簽名操作。
rk_security_setup_createkeys()
{mkdir -p $UBOOT/keyscd $UBOOT/keys# 生成的密鑰對放在uboot/keys目錄下$RK_SIGN_TOOL kk --bits 2048 --out ./ln -rsf private_key.pem dev.keyln -rsf public_key.pem dev.pubkey# TODO: Some rk_sign_tool may create privateKey.pem / publicKey.pem# 生成簽名證書openssl req -batch -new -x509 -key $UBOOT/keys/dev.key \-out $UBOOT/keys/dev.crt# system使用加密方式	if [ "$1" == "system-encryption" ]; thenopenssl rand -out $UBOOT/keys/system_enc_key -hex 32fi
}rk_security_setup_system_verity()
{target_image=$(readlink -f $1)outdir=$(cd $(dirname $target_image);pwd)security_system=$outdir/security_system.imgif [ -f "$outdir/security.info" ]; thensource $outdir/security.infoif [ "$(ls -l --time-style=long-iso $target_image | cut -d ' ' -f 6,7)" == "$touch" ]; thenecho "security_system.img not be updated!!!"return 0fifisectors=$(ls -l "$target_image" | awk '{printf $5}')hash_offset=$[(sectors / 1024 / 1024 + 2) * 1024 * 1024]tmp_file=$(mktemp)cp "$target_image" "$security_system"veritysetup --hash-offset=$hash_offset format "$security_system" "$security_system" > $tmp_fileecho "touch=\"$(ls -l --time-style=long-iso $target_image | cut -d ' ' -f 6,7)\"" > $outdir/security.infoecho "hash_offset=$hash_offset" >> $outdir/security.inforoot_hash=$(cat $tmp_file)echo "root_hash=$(echo ${root_hash##*:})" >> $outdir/security.info# cat "$tmp_file" >> $outdir/inform $tmp_file
}rk_security_setup_system_encryption()
{target_image=$(readlink -f $1)outdir=$(cd $(dirname $target_image);pwd)security_system=$outdir/security_system.imgkey=$(cat $UBOOT/keys/system_enc_key)cipher=aes-cbc-plainif [ -f "$outdir/security.info" ]; thensource $outdir/security.infoif [ "$(ls -l --time-style=long-iso $target_image | cut -d ' ' -f 6,7)" == "$touch" ]; thenecho "security_system.img not be updated!!!"return 0fifisectors=$(ls -l "$target_image" | awk '{printf $5}')sectors=$[(sectors + (1 * 1024 * 1024) - 1) / 512] # Align 1M / unit: 512 bytesloopdevice=$(losetup -f)mappername=encfs-$(shuf -i 1-10000000000000000000 -n 1)dd if=/dev/null of="$security_system" seek=$sectors bs=512sudo -S losetup $loopdevice "$security_system" < $UBOOT/keys/root_passwdsudo -S dmsetup create $mappername --table "0 $sectors crypt $cipher $key 0 $loopdevice 0 1 allow_discards" < $UBOOT/keys/root_passwdsudo -S dd if="$target_image" of=/dev/mapper/$mappername conv=fsync < $UBOOT/keys/root_passwdif sync; thensudo -S dmsetup remove $mappername < $UBOOT/keys/root_passwdfisudo -S losetup -d $loopdevice < $UBOOT/keys/root_passwdecho "touch=\"$(ls -l --time-style=long-iso $target_image | cut -d ' ' -f 6,7)\"" > $outdir/security.infoecho "sectors=$sectors" >> $outdir/security.infoecho "cipher=$cipher" >> $outdir/security.infoecho "key=$key" >> $outdir/security.info
}rk_security_setup_system()
{case $1 insystem-verity) shift; rk_security_setup_system_verity $@ ;;system-encryption) shift; rk_security_setup_system_encryption $@ ;;base) ;;*) exit -1;;esac
}rk_security_setup_ramboot_prebuild()
{check_method=$1shiftinit_in=$1shiftsecurity_file=$1shiftoptee_storage=$1case $check_method insystem-encryption) echo encryption ;;system-verity) echo verity ;;base) return ;;*) exit -1;;esacif [ ! -f "$init_in" ] || [ ! -f "$security_file" ]; thenecho -e "\e[41;1;37minit_in or security_file is missed\e[0m"exit -1fiinit_file="$(dirname $init_in)/init"cp $init_in $init_fileif [ "$check_method" == "system-encryption" ]; thensource "$security_file"sed -i "s/ENC_EN=/ENC_EN=true/" "$init_file"sed -i "s/CIPHER=/CIPHER=$cipher/" "$init_file"sed -i "s/SECURITY_STORAGE=RPMB/SECURITY_STORAGE=$optee_storage/" "$init_file"elsesource "$security_file"sed -i "s/ENC_EN=/ENC_EN=false/" "$init_file"sed -i "s/OFFSET=/OFFSET=$hash_offset/" "$init_file"sed -i "s/HASH=/HASH=$root_hash/" "$init_file"fised -i "s/# exec busybox switch_root/exec busybox switch_root/" "$init_file"echo "Generate ramdisk init for security"
}# 配置RK_SIGN_TOOL工具,導入需要使用的密鑰對,以及sign_flag配置值
rk_security_setup_sign_tool()
{# CHIP取$1的2~4字節內容,因為一般為rk開頭,如rk3568,所以要過濾掉前面的rk字段CHIP=${1: 2: 4}${RK_SIGN_TOOL} cc --chip $CHIP${RK_SIGN_TOOL} lk --key $UBOOT/keys/dev.key --pubkey $UBOOT/keys/dev.pubkey# RK_SIGN_INI為setting.ini配置文件if [ "$2" != "--burn-key-hash" ]; then# 將查找sign_flag = 開始的行,將該行替換為sign_flag =,即刪除后面的內容sed -i "/sign_flag=/s/.*/sign_flag=/" ${RK_SIGN_INI}else# 將查找sign_flag = 開始的行,將該行替換為sign_flag=0x20sed -i "/sign_flag=/s/.*/sign_flag=0x20/" ${RK_SIGN_INI}fi
}# 使用RK_SIGN_TOOL 工具簽名loader,uboot.img或者trust.img
rk_security_setup_uboot_avb_sign()
{# assert_var_in_list 查看$1是否在 "loader uboot trust"列表中assert_var_in_list $1 "loader uboot trust"# 如果 $3存在,拷貝$2到$3,因為$3為簽名后的文件,所以先拷貝一份過去,避免失敗后出問題if [ "$3" ]; thencp $2 $3DST=$3elseDST=$2ficase $1 inloader) ${RK_SIGN_TOOL} sl --loader $DST;;uboot|trust) ${RK_SIGN_TOOL} si --img $DST;;esac
}# AVB簽名,簽名boot或者recovery鏡像文件
rk_security_setup_avb_sign()
{assert_var_in_list $1 "boot recovery"STAGE=$1# 鏡像絕對路徑SRC=$(realpath $2)DST_DIR=$3 IMAGE_DIR="${RK_OUTDIR:-$UBOOT}/security"mkdir -p "$IMAGE_DIR"IMAGE="$IMAGE_DIR/$STAGE-security.img"rm -rf "$IMAGE"cd $RK_AVB_TOOL_DIR$RK_AVB_TOOL -s -${STAGE} $SRCcp ${RK_AVB_TOOL_DIR}/out/${STAGE}.img ${IMAGE_DIR}/${STAGE}-security.img[ "$STAGE" != "boot" ] || \cp ${RK_AVB_TOOL_DIR}/out/vbmeta.img ${IMAGE_DIR}/vbmeta.imgif [ "$DST_DIR" ]; thenDST_DIR=$(realpath $DST_DIR)ln -rsf ${IMAGE} $DST_DIR/${STAGE}.img[ "$STAGE" != "boot" ] || \cp ${IMAGE_DIR}/vbmeta.img $DST_DIR/vbmeta.imgficd -
}# FIT方案的簽名
rk_security_setup_sign()
{assert_var_in_list $1 "boot recovery"STAGE=$1SRC=$(realpath $2)DST_DIR=$3IMAGE_DIR="${RK_OUTDIR:-$UBOOT}/security"mkdir -p "$IMAGE_DIR"IMAGE="$IMAGE_DIR/$STAGE-security.img"rm -rf "$IMAGE"cd $UBOOTln -rsLf "$SRC" "$IMAGE_DIR/$STAGE.img"./scripts/fit.sh --${STAGE}_img "$(realpath $IMAGE_DIR/$STAGE.img)"mv $STAGE.img "$IMAGE"ln -rsf ${IMAGE} $DST_DIR/${STAGE}.imgcd "${RK_SDK_DIR:-..}"
}# -----------------------------------
# For SDK
# -----------------------------------
build_security_system()
{[ "$RK_ROOTFS_SYSTEM_BUILDROOT" ] || warning "rootfs is not buildroot!""$RK_SCRIPTS_DIR/mk-rootfs.sh"[ -z "$RK_SECURITY_CHECK_SYSTEM_VERITY" ] ||"$RK_SCRIPTS_DIR/mk-security.sh" security-rambootnotice "Security rootfs.img has update in output/firmware/rootfs.img"finish_build $@
}build_security_ramboot()
{check_config RK_SECURITY_INITRD_CFG || falsemessage "=========================================="message "          Start building security ramboot(buildroot)"message "=========================================="if [ ! -r "$RK_FIRMWARE_DIR/rootfs.img" ]; thennotice "Rootfs is not ready, building it for security...""$RK_SCRIPTS_DIR/mk-rootfs.sh"fiif [ "$RK_SECURITY_OPTEE_STORAGE_SECURITY" ]; thenOPTEE_STORAGE=SECURITYelseOPTEE_STORAGE=RPMBfi"$RK_SCRIPTS_DIR/mk-security.sh" ramboot_prebuild \$RK_SECURITY_CHECK_METHOD \$RK_SDK_DIR/buildroot/board/rockchip/common/security-ramdisk-overlay/init.in \$RK_OUTDIR/buildroot/images/security.info $OPTEE_STORAGEDST_DIR="$RK_OUTDIR/security-ramboot"IMAGE_DIR="$DST_DIR/images""$RK_SCRIPTS_DIR/mk-buildroot.sh" $RK_SECURITY_INITRD_CFG "$IMAGE_DIR"if [ "$RK_USE_FIT_IMG" ]; then"$RK_SCRIPTS_DIR/mk-ramboot.sh" "$DST_DIR" \"$IMAGE_DIR/rootfs.$RK_SECURITY_INITRD_TYPE" \"$RK_SECURITY_FIT_ITS"else"$RK_SCRIPTS_DIR/mk-ramboot.sh" "$DST_DIR" \"$IMAGE_DIR/rootfs.$RK_SECURITY_INITRD_TYPE"fi"$RK_SCRIPTS_DIR/mk-security.sh" sign boot \$DST_DIR/ramboot.img $RK_FIRMWARE_DIR/notice "Security boot.img has update in output/firmware/boot.img"finish_build $@
}# HooksBUILD_CMDS="security-createkeys security-misc security-ramboot security-system"# sign參數后面跟 需要進行前面的鏡像名稱,比如sing loader
HID_CMDS="createkeys misc system ramboot_prebuild sign"build_avb_sign()
{case $1 inloader|uboot|trust)# rk_security_setup_sign_tool,配置RK_SIGN_TOOL工具,導入需要使用的密鑰對,以及sign_flag配置值# RK_SECURITY_BURN_KEY=y 在buildroot中進行配置rk_security_setup_sign_tool $RK_CHIP \"$(test $RK_SECURITY_BURN_KEY && \echo --burn-key-hash || \echo --debug-key-hash)"# rk_security_setup_uboot_avb_sign,使用RK_SIGN_TOOL 工具簽名loader,uboot.img或者trust.img	# 在對uboot.img進行簽名時失敗,# Image is /home/mingl/VRC-AE05-01-gerrit/rk3568_bsp/output/firmware/uboot.img# the image did not support to signrk_security_setup_uboot_avb_sign $@ ;;recovery)# rk_security_setup_avb_sign,AVB簽名,簽名boot或者recovery鏡像文件rk_security_setup_avb_sign $@ \$[ $(rk_partition_size_kb recovery) * 1024 ];;*)# 默認情況走這個分支rk_security_setup_avb_sign $@;;esac
}build_hook()
{case $1 insecurity-createkeys)  #使用RK_SIGN_TOOL生成簽名loader,uboot的密鑰。rk_security_setup_createkeys $RK_SECURITY_CHECK_METHOD;;security-misc)if [ "$RK_SECURITY_CHECK_SYSTEM_ENCRYPTION" ]; then"$RK_SCRIPTS_DIR/mk-misc.sh"fi;;security-ramboot) build_security_ramboot ;;security-system) build_security_system ;;esac# $1 參數必須是 createkeys misc system ramboot_prebuild sign內的選項,否則return 0;echo $HID_CMDS | fgrep "$1" -wq || return 0append=$1shiftcase $append insign)# RK_SECUREBOOT_AVB=y 需要在buildroot中進行配置,表明開啟AVB安全功能# 調用build_avb_sign,失敗則調用rk_security_setup_$append 函數繼續進行處理test "$RK_SECUREBOOT_AVB" && \build_avb_sign $@ || \rk_security_setup_$append $@  #rk_security_setup_sign 函數繼續進行處理;;*) rk_security_setup_$append $@ ;;esac
}usage_hook()
{echo -e "security-createkeys               \tcreate keys for security"echo -e "security-misc                     \tbuild misc with system encryption key"echo -e "security-ramboot                  \tbuild security ramboot"echo -e "security-system                   \tbuild security system"
}clean_hook()
{rm -rf $RK_OUTDIR/security*
}# RK_SESSION_DIR="$RK_OUTDIR/sessions"
[ -z "$RK_SESSION" ] || \source "${RK_BUILD_HELPER:-$(dirname "$(realpath "$0")")/../build-hooks/build-helper}"[ -z "$1" ] || build_hook $@

?由于筆者使用的是linux,其中沒有要求對只讀分區的簽名校驗。 安卓系統的話,可能需要對system分區進行簽名和校驗,就需要將瑞芯微官方文檔中對只讀分區進行簽名校驗的流程完成,

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/79276.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/79276.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/79276.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[操作系統] 線程互斥

文章目錄 背景概念線程互斥的引出互斥量鎖的操作初始化 (Initialization)靜態初始化動態初始化 加鎖 (Locking)阻塞式加鎖非阻塞式加鎖 (嘗試加鎖/一般不考慮) 解鎖 (Unlocking)銷毀 (Destruction)設置屬性 (Setting Attributes - 通過 pthread_mutex_init) 鎖本身的保護互斥鎖…

【神經網絡與深度學習】兩種加載 pickle 文件方式(joblib、pickle)的差異

引言 從深度學習應用到數據分析的多元化需求出發&#xff0c;Python 提供了豐富的工具和模塊&#xff0c;其中 pickle 和 joblib 兩種方式在加載數據文件方面表現尤為突出。不同場景對性能、兼容性以及后續處理的要求不盡相同&#xff0c;使得這兩種方式各顯優勢。本文將通過深…

Electron 入門指南

Electron 入門指南 Electron 是一個使用 JavaScript、HTML 和 CSS 構建跨平臺桌面應用的框架。通過 Electron&#xff0c;你可以利用 Web 技術開發出功能強大的桌面應用程序&#xff0c;并且能夠運行在 Windows、Mac 和 Linux 系統上。 本文將帶你從零開始構建一個簡單的 Ele…

編程中如何與AI交互-結構化輸入和理解確認機制

一 結構化輸入是什么 &#x1f4cc; 結構化輸入的定義&#xff1a; 結構化輸入是指以清晰、分層、有邏輯的格式向 AI 輸入信息&#xff0c;使其更容易解析內容、抓住重點&#xff0c;并準確回答問題。 &#x1f4e6; 舉個例子&#xff08;編程場景&#xff09;&#xff1a; 非…

13:傅里葉變換

傅立葉變換(FT, Fourier Transform)的作用是將一個信號由時域變換到頻域。其實就是把數據由橫坐標時間、縱坐標采樣值的波形圖格式&#xff0c;轉換為橫坐標頻率、縱坐標振幅(或相位)的頻譜格式。換后可以很明顯地看出一些原先不易察覺的特征。 有些信號在時域上是很難看出什么…

基于單片機的音頻信號處理系統設計(一)

項目名稱:基于單片機的音頻信號處理系統設計學院名稱:信息學院學生姓名:學號專業年級:指導教師:教師職稱:教授企業導師:目 錄 摘 要 Abstract 1 前言 1.1研究背景與意義 <

機器學習實操 第一部分 機器學習基礎 第8章 降維技術

機器學習實操 第一部分 機器學習基礎 第8章 降維技術 內容概要 第8章探討了降維技術&#xff0c;這些技術在處理高維數據時至關重要。高維數據不僅會使訓練過程變得極其緩慢&#xff0c;還會增加找到良好解決方案的難度&#xff0c;這就是所謂的維度災難問題。幸運的是&#…

微信小程序 XSS 防護知識整理

場景1&#xff1a;用戶輸入表單&#xff08;如評論框&#xff09; 錯誤做法&#xff1a;直接渲染未過濾的用戶輸入 // WXML <view>{{ userInput }}</view>// JS&#xff08;用戶輸入了惡意內容&#xff09; Page({data: { userInput: <script>alert("…

MySQL 服務搭建

&#x1f4a2;歡迎來到張翊塵的開源技術站 &#x1f4a5;開源如江河&#xff0c;匯聚眾志成。代碼似星辰&#xff0c;照亮行征程。開源精神長&#xff0c;傳承永不忘。攜手共前行&#xff0c;未來更輝煌&#x1f4a5; 文章目錄 在線安裝Ubuntu/Debian更新系統包索引安裝 MySQL …

【Java面試筆記:進階】23.請介紹類加載過程,什么是雙親委派模型?

Java的類加載機制是JVM的核心組成部分,其過程分為三個階段,并采用雙親委派模型來保證類加載的安全性和一致性。 1.類加載過程 1.加載階段(Loading) 核心任務:查找并加載類的二進制字節流(如.class文件)。具體行為: 將字節碼數據從不同數據源(如文件系統、網絡等)讀…

UN R79 關于車輛轉向裝置形式認證的統一規定(正文部分1)

UN R79法規是針對轉向裝置的型式認證法規&#xff0c;涉及A/B1/C類的橫向控制輔助駕駛功能&#xff0c;對各功能的功能邊界、性能要求、狀態提示、故障警示以及型式認證要提交的信息做了規范&#xff0c;本文結合百度文心一言對法規進行翻譯&#xff0c;并結合個人理解對部分內…

[隨筆] 升級uniapp舊項目的vue、pinia、vite、dcloudio依賴包等

匯總 # 升級uniapp項目dcloudio整體依賴&#xff0c;建議執行多次 # 會順帶自動更新/升級vue的版本 npx dcloudio/uvmlatest alpha# 檢查 pinia 的最新版本 npm view pinia version# 更新項目 pinia 到最新版本 npm update pinia# 更新項目 pinia 到特定的版本 # 首先&#xf…

【使用小皮面板 + WordPress 搭建本地網站教程】

&#x1f680; 使用小皮面板 WordPress 搭建本地網站教程&#xff08;快速上手&#xff09; 本教程將手把手教你如何使用 小皮面板&#xff08;XAMPP 類似工具&#xff09; 和 WordPress 搭建一個完全本地化的網站環境。適合 初學者 / 博主 / Web開發者 本地練習使用&#xf…

[更新完畢]2025五一杯A題五一杯數學建模思路代碼文章教學:支路車流量推測問題

完整內容請看文章最下面的推廣群 支路車流量推測問題 摘要 本文針對支路車流量推測問題展開研究&#xff0c;通過建立數學模型解決不同場景下的車流量分析需求。 針對問題一&#xff08;Y型道路場景&#xff09;&#xff0c;研究兩支路匯入主路的車流量推測。通過建立線性增長…

前端面試寶典---webpack原理解析,并有簡化版源碼

前言 先看一下webpack打包后的bundle.js&#xff0c;前邊的直接掃一眼就過&#xff0c;可以發現這個立即執行函數的形參就是一個&#xff0c;key為引入文件路徑&#xff0c;value為該模塊代碼的函數。 所以比較重要的就是通過webpack的配置文件中的entry的入口文件&#xff0c…

面試的各種類型

面試是用人單位選拔人才的重要環節&#xff0c;常見的面試類型有結構化面試、半結構化面試、非結構化面試和壓力面試&#xff0c;每種類型都有其特點和應對策略。 一、結構化面試 特點&#xff1a; 標準化流程 面試流程固定&#xff0c;考官會按照預先設計好的問題清單依次向…

vue3定義全局防抖指令

文章目錄 代碼參數講解 在寫項目時&#xff0c;總會有要進行防抖節流的時候&#xff0c;如果寫一個debounce函數的話 用起來代碼總會是有點長的&#xff0c;因此想到了用一個全局指令進行輸入框的防抖&#xff0c;畢竟全局指令使用時只要v-xxx就行了&#xff0c;非常方便 代碼…

WebDeveloper 流量分析、sudo提權,靶場通關WP

一、信息收集 1、主機探測 arp-scan -l netdiscover -i eth0 -r 192.168.33.0/24 nmap -sP 192.168.66.0/24 2、端口掃描 nmap -sS -sV 192.168.66.141 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0) 80/tcp op…

某化工廠運維升級:智和信通運維平臺實現工業交換機智能管理

隨著某化工廠數字化轉型的加速推進&#xff0c;其生產過程對復雜網絡和IT設備的依賴程度日益加深。當前的網絡不僅承載著生產控制系統&#xff08;如DCS、PLC等&#xff09;的通信需求&#xff0c;還同時支持辦公自動化、安防監控、工業物聯網&#xff08;IoT&#xff09;等多種…

React:封裝一個編輯文章的組件

封裝一個編輯文章的組件,就要用到富文本編輯器,支持標題、內容、標簽等的編輯,并且能夠保存和取消。 首先,我需要考慮用戶的具體需求。編輯文章組件通常需要哪些功能?標題輸入、內容編輯、標簽管理、保存和取消按鈕。可能還需要自動保存草稿、驗證輸入、錯誤提示等功能。用…