blob: f7e0ec6cab6a6969cf4c61346482c834d9f9c727 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001inherit hsm-sign-env
2
3python __anonymous () {
4 depends = d.getVar("DEPENDS", True)
5 depends = "%s u-boot-mkimage-native dtc-native openssl-native" % depends
6 d.setVar("DEPENDS", depends)
7}
8
9# split input string to multiple quadbyte word (with 0x prefix for each word)
10# input:
11# $1: input string, e.g., 0123456789ABCDEF...
12# $2: "swap", to do byte swap in each quadbyte; otherwise, no swap
13# output:
14# standard output: 0x67452301 0xEFCDAB89 ... if $2 = "swap"
15# 0x01234567 0x89ABCDEF ... otherwise
16split_str_to_quadbytes() {
17 quadbytes=""
18
19 if [ $2 = "swap" ]; then
20 sed_cmd="sed s,\(..\)\(..\)\(..\)\(..\),\4\3\2\1,g"
21 else
22 sed_cmd="sed s,\(..\)\(..\)\(..\)\(..\),\1\2\3\4,g"
23 fi
24
25 if [ ! -z "$1" ]; then
26 for i in $(seq 1 8 ${#1}); do
27 end_idx=`echo "${i} + 7" | bc`
28 qb=`echo ${1} | cut -c${i}-${end_idx} | ${sed_cmd}`
29 quadbytes="${quadbytes} 0x${qb}"
30 done
31 # trim leading space
32 awk '{$quadbytes=$quadbytes};1'
33 fi
34
35 echo $quadbytes
36}
37
38# Emit fit header
39# input param:
40# $1: fit its
41fitimage_emit_fit_header() {
42 cat << EOF >> $1
43/dts-v1/;
44
45/ {
46 description = "bl";
47 #address-cells = <1>;
48EOF
49}
50
51# Emit the fitimage image section
52# input param:
53# $1: fit its
54# $2: path to padding binary
55# $3: path to lk binary
56# $4: lk load address
57# $5: lk entry address
58# $6: hash algorithm
59fitimage_emit_fit_image_section() {
60 cat << EOF >> $1
61
62 images {
63 bl@1 {
64 description = "bl";
65 padding = /incbin/("${2}");
66 data = /incbin/("${3}");
67 type = "kernel";
68 compression = "none";
69 load = <${4}>;
70 entry = <${5}>;
71 hash@1 {
72 algo = "${6}";
73 };
74 };
75 };
76EOF
77}
78
79# Emit fitimage configuration section
80# input param:
81# $1: fit its
82# $2: hash algorithm
83# $3: rsa algorithm
84# $4: key name hint
85# $5: aes iv
86fitimage_emit_fit_conf_section() {
87 if [ "${ACK_EN}" = "yes" ]; then
88 # split aes iv to N 32-bit words
89 quadbytes=$(split_str_to_quadbytes ${5} noswap)
90 ack_iv_prop="ack_iv = <${quadbytes}>;"
91 else
92 ack_iv_prop=
93 fi
94
95 cat << EOF >> $1
96
97 configurations {
98 default = "conf@1";
99 conf@1 {
100 description = "bl";
101 kernel = "bl@1";
102 ${ack_iv_prop}
103 signature@1 {
104 algo = "${2},${3}";
105 key-name-hint = "${4}";
106 sign-images = "kernel";
107 };
108 };
109 };
110EOF
111}
112
113# Emit fitimage trusted-key-certificate oem section
114# input param:
115# $1: fit its
116fitimage_emit_fit_tkc_oem_section() {
117 cat << EOF >> $1
118
119 trusted-key-certificate {
120 sign-node {
121 device-check = "skip-device-id-check";
122 device-id = "N0cI//dxndWXnsh11WzSKG9tPPfs";
123 trusted-key {
124 key-name-hint = "TierPubKey";
125 };
126 };
127 };
128EOF
129}
130
131# Emit fitimage trusted-key-certificate tier section
132# input param:
133# $1: fit its
134# $2: TKC.dtsi
135fitimage_emit_fit_tkc_tier_section() {
136 cat << EOF >> $1
137
138 /include/ "$2"
139EOF
140}
141
142# Emit fitimage fit end
143# input param:
144# $1: fit its
145fitimage_emit_fit_end() {
146 cat << EOF >> $1
147};
148EOF
149}
150
151# get_fit_data_offset: get data offset from fit image
152# input param:
153# $1: fit image
154get_fit_data_offset() {
155 FIT_IMAGE=$1
156
157 TMPF=$(mktemp ${WORKDIR}/dump-fit-img.XXXXXX)
158
159 # dump fit image
160 fdtdump -d ${FIT_IMAGE} > ${TMPF}
161
162 # get props
163 LINE=$(grep -n '^ *data' ${TMPF} | grep -o '^[0-9]*')
164 LINE=`expr ${LINE} - 1`
165 ADDR=$(grep -n "^// [[:xdigit:]]*: value" ${TMPF} | grep "^${LINE}://" | \
166 grep -o " [[:xdigit:]]*" | grep -o "[[:xdigit:]]*")
167
168 # remove temp files
169 rm -f ${TMPF}
170
171 echo ${ADDR}
172}
173
174# check_fit_image: check fit image and also check load/entry address if 2nd
175# param was present
176# input param:
177# $1: fit image
178# $2: if present, will also check load and entry validity
179check_fit_image() {
180 FIT_IMAGE=$1
181 CHECK_OPT=$2
182
183 # check default cfg
184 CFG=$(fdtget ${FIT_IMAGE} /configurations default)
185 if [ "${CFG}" = "" ]; then
186 echo "ERROR: no default in /configurations"
187 exit 1
188 fi
189
190 # check image name
191 IMG_NAME=$(fdtget ${FIT_IMAGE} /configurations/${CFG} kernel)
192 if [ "${IMG_NAME}" = "" ]; then
193 echo "ERROR: no image name (kernel prop) in /configurations/${CFG}"
194 exit 1
195 fi
196
197 # check data
198 DATA=$(fdtget ${FIT_IMAGE} /images/${IMG_NAME} data)
199 if [ "${DATA}" = "" ]; then
200 echo "ERROR: no data in /images/${IMG_NAME}"
201 exit 1
202 fi
203
204 # check load
205 LOAD_D=$(fdtget ${FIT_IMAGE} /images/${IMG_NAME} load)
206 if [ "$LOAD_D" = "" ]; then
207 echo "ERROR: no load in /images/${IMG_NAME}"
208 exit 1
209 fi
210
211 # check entry
212 ENTRY_D=$(fdtget ${FIT_IMAGE} /images/${IMG_NAME} entry)
213 if [ "$ENTRY_D" = "" ]; then
214 echo "ERROR: no entry in /images/${IMG_NAME}"
215 exit 1
216 fi
217
218 if [ "${CHECK_OPT}" != "" ]; then
219 OFFSET=$(get_fit_data_offset ${FIT_IMAGE})
220 LOAD=$(printf "%x" ${LOAD_D})
221 if [ "`expr ${LOAD} : '.*\(....\)'`" != "${OFFSET}" ]; then
222 echo ERROR: load ${LOAD} is not align with data offset ${OFFSET}
223 exit 1
224 fi
225
226 LEN=$(echo ${DATA} | wc -w)
227 ENTRY=$(printf "%x" ${ENTRY_D})
228 END_D=`echo "${LOAD_D} + ${LEN} * 4" | bc`
229 END=$(printf "%x" ${END_D})
230 if [ ${ENTRY_D} -lt ${LOAD_D} -o ${END_D} -le ${ENTRY_D} ]; then
231 echo ERROR: entry ${ENTRY} is not in data ${LOAD} - ${END}
232 exit 1
233 fi
234 fi
235}
236
237# generate fit image: generate lk image in fit format
238# input param:
239# $1: fit image its file
240# $2: key dir
241# $3: output file
242gen_fit_image() {
243 FIT_ITS=$1
244 KEYDIR=$2
245 OUT=$3
246 DTB=$(mktemp ${WORKDIR}/dtb.XXXXXX)
247 KEYDTSI=$(mktemp ${WORKDIR}/key.XXXXXX.dtsi)
248 KEYITS=$(mktemp ${WORKDIR}/key-fit-image.XXXXXX.its)
249
250 if [ "${SBC_SIGN_ALGO}" = "ecc" ]; then
251 case "${SBC_ECC_ALGO}" in
252 nistp256)
253 HSM_SBC_KEY=${SBC_KEY_ECC256}
254 ;;
255 nistp384)
256 HSM_SBC_KEY=${SBC_KEY_ECC384}
257 ;;
258 nistp521)
259 HSM_SBC_KEY=${SBC_KEY_ECC521}
260 ;;
261 *)
262 echo ${SBC_ECC_ALGO} ": not supported."
263 exit 1
264 ;;
265 esac
266 else
267 case "${SBC_RSA_ALGO}" in
268 rsa2048 | rsassa-pss2048)
269 HSM_SBC_KEY=${SBC_KEY}
270 ;;
271 rsa3072 | rsassa-pss3072)
272 HSM_SBC_KEY=${SBC_KEY_RSA3072}
273 ;;
274 rsa4096 | rsassa-pss4096)
275 HSM_SBC_KEY=${SBC_KEY_RSA4096}
276 ;;
277 *)
278 echo ${SBC_RSA_ALGO} ": not supported."
279 exit 1
280 ;;
281 esac
282 fi
283 echo "HSM_SBC_KEY name is ${HSM_SBC_KEY}"
284
285 echo "/dts-v1/; / {};" | dtc -O dtb > ${DTB}
286 if [ "${TKC_SUPPORT}" = "oem" ]; then
287 ${HSM_ENV} HSM_KEY_NAME=${HSM_SBC_KEY} ${FIT_IMG_TOOL} -f ${FIT_ITS} -k ${KEYDIR} -K ${DTB} -g ${TKC_PUBLIC_KEY_TIER} ${OUT}
288 elif [ "${TKC_SUPPORT}" = "tier" ]; then
289 ${HSM_ENV} HSM_KEY_NAME=${HSM_SBC_KEY} ${FIT_IMG_TOOL} -f ${FIT_ITS} -k ${KEYDIR} -K ${DTB} -u ${TKC_PUBLIC_KEY_OEM} ${OUT}
290 else
291 ${HSM_ENV} HSM_KEY_NAME=${HSM_SBC_KEY} ${FIT_IMG_TOOL} -f ${FIT_ITS} -k ${KEYDIR} -K ${DTB} ${OUT}
292 fi
293
294 dtc -I dtb ${DTB} | tail -n+2 > ${KEYDTSI}
295
296 sed "s,\/dts-v1\/;,\0\n\/include\/ \"${KEYDTSI}\"," < ${FIT_ITS} > ${KEYITS}
297 ${HSM_ENV} HSM_KEY_NAME=${HSM_SBC_KEY} ${FIT_IMG_TOOL} -f ${KEYITS} -k ${KEYDIR} ${OUT}
298
299 # remove temporary files
300 rm -f ${DTB} ${KEYDTSI} ${KEYITS}
301}
302
303# gen_sbc_key_hash
304# input param:
305# $1: fit image
306gen_sbc_key_hash() {
307 FDT_IMG=$1
308 TMP_FILE=$(mktemp ${WORKDIR}/col_rgn.XXXXXX.bin)
309
310 DEF_CONF=`fdtget -t s ${FDT_IMG} /configurations default`
311 SIG_NODE=`fdtget -l ${FDT_IMG} /configurations/${DEF_CONF}`
312 KEY_HINT=`fdtget -t s ${FDT_IMG} /configurations/${DEF_CONF}/${SIG_NODE} key-name-hint`
313 SHAX=`fdtget -t s ${FDT_IMG} /configurations/${DEF_CONF}/${SIG_NODE} algo | cut -d, -f1`
314 ${WORKDIR}/fit-lk/extract_region ${FDT_IMG} ${TMP_FILE} /signature/key-${KEY_HINT}
315 KEY_HASH=`${SHAX}sum ${TMP_FILE} | cut -d " " -f 1`
316 echo "Hash algo: ${SHAX}"
317 echo "key_hash: ${KEY_HASH}"
318
319 key_hash_str=$(split_str_to_quadbytes ${KEY_HASH} swap)
320
321 idx=0
322 for qb in $key_hash_str; do
323 echo "keyhash_${idx}: ${qb}"
324 idx=`echo "${idx} + 1" | bc`
325 done
326
327 rm -f ${TMP_FILE}
328}
329
330# print_aes_key_iv
331# $1: aes key
332# $2: aes iv
333print_aes_key_iv() {
334 # print aes keys
335 echo "AES_KEY(AC_KEY)=${1}"
336 quadbytes=$(split_str_to_quadbytes ${1} swap)
337 idx=0
338 for qb in $quadbytes; do
339 echo "AC_KEY${idx}: ${qb}"
340 idx=`echo "${idx} + 1" | bc`
341 done
342
343 # print aes iv
344 echo "AES_IV=${2}"
345 quadbytes=$(split_str_to_quadbytes ${2} noswap)
346 echo "prop ack_iv=<${quadbytes}>"
347}
348
349gen_lk_fit_header() {
350 # generate temp files
351 BL_BIN=$(mktemp ${WORKDIR}/bl.XXXXXX.bin)
352 FIT_LK_IMG=${WORKDIR}/fit-lk.img
353 FIT_ITS=$(mktemp ${WORKDIR}/fit-bl-image.XXXXXX.its)
354 KEYDIR=${WORKDIR}/lk-key
355 PADDING=$(mktemp ${WORKDIR}/padding.XXXXXX.bin)
356
357 if [ "${ACK_EN}" = "yes" ]; then
358 # output AES encrypted BL image to working directory
359 openssl enc -e -aes-128-cbc -in ${LK_OUT}/build-${LK_PROJECT}/${LK_BINARY} \
360 -out ${BL_BIN} -K ${AES_KEY} -iv ${AES_IV}
361 else
362 # copy raw lk binary to working directory
363 cp ${LK_OUT}/build-${LK_PROJECT}/${LK_BINARY} ${BL_BIN}
364 fi
365
366 # generate a zero-size padding binary
367 touch ${PADDING}
368
369 # prepare rsa key
370 mkdir -p ${KEYDIR}
371
372 if [ "${SBC_SIGN_ALGO}" = "ecc" ]; then
373 case "${SBC_ECC_ALGO}" in
374 nistp256)
375 cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC256}_priv.pem ${KEYDIR}/dev_priv.key
376 cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC256}_public.pem ${KEYDIR}/dev_public.key
377 ;;
378 nistp384)
379 cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC384}_priv.pem ${KEYDIR}/dev_priv.key
380 cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC384}_public.pem ${KEYDIR}/dev_public.key
381 ;;
382 nistp521)
383 cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC521}_priv.pem ${KEYDIR}/dev_priv.key
384 cp -f ${MTK_KEY_DIR}/${SBC_KEY_ECC521}_public.pem ${KEYDIR}/dev_public.key
385 ;;
386 *)
387 echo ${SBC_ECC_ALGO} ": not supported."
388 exit 1
389 ;;
390 esac
391 else
392 case "${SBC_RSA_ALGO}" in
393 rsa2048 | rsassa-pss2048)
394 cp -f ${MTK_KEY_DIR}/${SBC_KEY}.crt ${KEYDIR}/dev.crt
395 cp -f ${MTK_KEY_DIR}/${SBC_KEY}.pem ${KEYDIR}/dev.key
396 ;;
397 rsa3072 | rsassa-pss3072)
398 cp -f ${MTK_KEY_DIR}/${SBC_KEY_RSA3072}.crt ${KEYDIR}/dev.crt
399 cp -f ${MTK_KEY_DIR}/${SBC_KEY_RSA3072}.pem ${KEYDIR}/dev.key
400 ;;
401 rsa4096 | rsassa-pss4096)
402 cp -f ${MTK_KEY_DIR}/${SBC_KEY_RSA4096}.crt ${KEYDIR}/dev.crt
403 cp -f ${MTK_KEY_DIR}/${SBC_KEY_RSA4096}.pem ${KEYDIR}/dev.key
404 ;;
405 *)
406 echo ${SBC_RSA_ALGO} ": not supported."
407 exit 1
408 ;;
409 esac
410 fi
411
412 # key for trusted-key-certificate
413 if [ "${TKC_SUPPORT}" = "oem" ]; then
414 if [ "${SBC_SIGN_ALGO}" = "ecc" ]; then
415 cp -f ${MTK_KEY_DIR}/${TKC_PUBLIC_KEY_TIER}.pem ${KEYDIR}/tier_public.key
416 elif [ "${SBC_SIGN_ALGO}" = "rsa" ]; then
417 cp -f ${MTK_KEY_DIR}/${TKC_PUBLIC_KEY_TIER}.crt ${KEYDIR}/tier_public.crt
418 fi
419 elif [ "${TKC_SUPPORT}" = "tier" ]; then
420 if [ "${SBC_SIGN_ALGO}" = "ecc" ]; then
421 cp -f ${MTK_KEY_DIR}/${TKC_PUBLIC_KEY_OEM}.pem ${KEYDIR}/oem_public.key
422 elif [ "${SBC_SIGN_ALGO}" = "rsa" ]; then
423 cp -f ${MTK_KEY_DIR}/${TKC_PUBLIC_KEY_OEM}.crt ${KEYDIR}/oem_public.crt
424 fi
425 fi
426
427 # generate base its file
428 fitimage_emit_fit_header ${FIT_ITS}
429
430 # if TKC is supportted, place it here
431 if [ "${TKC_SUPPORT}" = "oem" ]; then
432 fitimage_emit_fit_tkc_oem_section ${FIT_ITS} ${SBC_HASH_ALGO} ${SBC_ECC_ALGO} dev
433 elif [ "${TKC_SUPPORT}" = "tier" ]; then
434 fitimage_emit_fit_tkc_tier_section ${FIT_ITS} ${MTK_KEY_DIR}/TKC.dtsi
435 fi
436
437 fitimage_emit_fit_image_section ${FIT_ITS} ${PADDING} ${BL_BIN} \
438 ${LK_LOADADDRESS} ${LK_ENTRYPOINT} ${IMAGE_HASH_ALGO}
439
440 if [ "${SBC_SIGN_ALGO}" = "ecc" ]; then
441 fitimage_emit_fit_conf_section ${FIT_ITS} ${SBC_HASH_ALGO} ${SBC_ECC_ALGO} dev ${AES_IV}
442 else
443 fitimage_emit_fit_conf_section ${FIT_ITS} ${SBC_HASH_ALGO} ${SBC_RSA_ALGO} dev ${AES_IV}
444 fi
445
446 fitimage_emit_fit_end ${FIT_ITS}
447
448 # 1st pass: generate fit-lk image to get padding size
449 gen_fit_image ${FIT_ITS} ${KEYDIR} ${FIT_LK_IMG}
450 check_fit_image ${FIT_LK_IMG}
451
452 # get data offset and calculate padding size
453 # padding size = lk load offset - data offset
454 DATA_OFFSET=$(get_fit_data_offset ${FIT_LK_IMG})
455 DATA_OFFSET_HEX=0x${DATA_OFFSET}
456 DATA_OFFSET_D=$(printf "%d" ${DATA_OFFSET_HEX})
457 LK_LOAD_OFFSET_D=$(printf "%d" ${LK_LOAD_OFFSET})
458 PADDING_SIZE=`echo "${LK_LOAD_OFFSET_D} - ${DATA_OFFSET_D}" | bc`
459
460 rm -f ${PADDING}
461 dd if=/dev/zero of=${PADDING} bs=1 count=${PADDING_SIZE}
462
463 # 2nd pass: generate final fit-lk image
464 gen_fit_image ${FIT_ITS} ${KEYDIR} ${FIT_LK_IMG}
465 check_fit_image ${FIT_LK_IMG} all
466
467 cp ${FIT_LK_IMG} ${WORKDIR}/${LK_IMAGE}
468
469 # gen key hash for convenience
470 gen_sbc_key_hash ${FIT_LK_IMG}
471
472 # output aes key and iv for reference
473 if [ "${ACK_EN}" = "yes" ]; then
474 print_aes_key_iv ${AES_KEY} ${AES_IV}
475 fi
476
477 # remove temp files
478 rm -f ${BL_BIN} ${FIT_ITS} ${PADDING}
479 rm -rf ${KEYDIR}
480}
481
482gen_lk_gfh_header() {
483 cp ${LK_OUT}/build-${LK_PROJECT}/${LK_BINARY} ${WORKDIR}/temp_gfh
484
485 if [ "${SECURE_BOOT_ENABLE}" = "yes" ]; then
486 cp ${MTK_KEY_DIR}/${SBC_KEY}.pem ${KEY_DIR}/root_prvk.pem
487 fi
488
489 python ${PBP_DIR}/pbp.py -g ${GFH_DIR}/${TARGET_PLATFORM}/gfh_conf.ini \
490 -i ${KEY_DIR}/lk_key.ini -func sign \
491 -o ${WORKDIR}/temp_gfh ${WORKDIR}/temp_gfh
492
493 if [ "${BOOTDEV_TYPE}" != "nand" ]; then
494 python ${DEV_INFO_HDR_TOOL} \
495 ${BOOTDEV_TYPE} ${WORKDIR}/temp_gfh ${WORKDIR}/${LK_IMAGE}
496 else
497 cp ${WORKDIR}/temp_gfh ${WORKDIR}/${LK_IMAGE}
498 fi
499}