blob: 27f455e01194aff8b9278b7e4d495d59eef7e56b [file] [log] [blame]
developer23f9f0f2023-06-15 13:06:25 +08001diff --git a/scripts/enc-rfsk.sh b/scripts/enc-rfsk.sh
2new file mode 100755
3index 0000000..d396127
4--- /dev/null
5+++ b/scripts/enc-rfsk.sh
6@@ -0,0 +1,194 @@
7+#!/bin/bash
8+# use roe-key to encrypt rootfs-key, and generate fit-secret
9+usage() {
10+ printf "Usage: %s -s build_dir -d key_dir -f fit" "$(basename "$0")"
11+ printf "encrypt rootfs key: [-k roe_key] "
12+ printf "generate FIT-secret: [-k roe_key -c config_name]\n"
13+ printf "\n\t-c ==> config name with signature node"
14+ printf "\n\t-d ==> key_directory"
15+ printf "\n\t-f ==> fit image file"
16+ printf "\n\t-k ==> roe key"
17+ printf "\n\t-s ==> build directory"
18+ exit 1
19+}
20+
21+hex2bin() {
22+ $PERL -e 'print pack "H*", <STDIN>'
23+}
24+
25+bin2hex() {
26+ od -An -t x1 -w128 | sed "s/ //g"
27+}
28+
29+hkdf() {
30+ local key=$1
31+ local info=$2
32+ local salt=$3
33+ local k_derived=$(${OPENSSL} kdf -keylen 32 -kdfopt digest:SHA2-256 \
34+ -kdfopt hexkey:$(cat ${key} | bin2hex) \
35+ -kdfopt hexsalt:$salt \
36+ -kdfopt info:$info HKDF | sed "s/://g")
37+ echo $k_derived
38+}
39+
40+gen_aes_key() {
41+ out=$1
42+ $OPENSSL rand -out $out 32
43+}
44+
45+aes_cbc_enc() {
46+ local in=$1
47+ local out=$2
48+ local key=$3
49+ local iv=$(${OPENSSL} rand -hex 16)
50+ $OPENSSL enc -e -aes-256-cbc -in $in -out ${out}.tmp -K $key -iv $iv
51+
52+ echo -n $iv | hex2bin > $out
53+ cat ${out}.tmp >> $out
54+ rm ${out}.tmp
55+}
56+
57+aes_gcm_enc() {
58+ local in=$1
59+ local out=$2
60+ local key=$3
61+ local aad=$4
62+ local iv=$(${OPENSSL} rand -hex 12)
63+ $AESGCM -e -i $in -o $out -k $key -n $iv -a $aad
64+}
65+
66+# encrypt data with AES
67+# encrypted-data-format:
68+# -----------------------------------------------
69+# | salt | iv | k-tempx.enc | iv | tag | in.enc |
70+# -----------------------------------------------
71+enc_data() {
72+ local k_temp=$1
73+ local in=$2
74+ local out=$3
75+ local info=$4
76+ local salt=$(${OPENSSL} rand -hex 16)
77+
78+ echo -n $salt | hex2bin > $out
79+
80+ # encrypt k-tempx
81+ aes_cbc_enc $k_temp ${out}.tmp $(hkdf ${ROE_KEY}.key ${info} ${salt})
82+
83+ cat ${out}.tmp >> $out
84+
85+ aad=$(cat ${out} | bin2hex)
86+ # encrypt in
87+ aes_gcm_enc $in ${out}.tmp $(cat $k_temp | bin2hex) $aad
88+
89+ cat ${out}.tmp >> $out
90+ rm ${out}.tmp
91+}
92+
93+# generate FIT-secret and insert back into FIT
94+gen_fit_secret() {
95+ echo "Generating fit-secret"
96+
97+ if [ ! -f "${FIT}" ]; then
98+ printf "%s not found\n" "${FIT}"
99+ exit 1
100+ fi
101+
102+ SECRETS_DIR=$BUILD_DIR/fit-secrets
103+ if [ ! -d "${SECRETS_DIR}" ]; then
104+ mkdir -p $SECRETS_DIR
105+ fi
106+
107+ LD_LIBRARY_PATH=${LIBFDT_PATH} \
108+ $FDTGET $FIT /configurations/$CONFIG/signature value -t bi > \
109+ $SECRETS_DIR/$FIT_NAME-signature.tmp || exit 1
110+
111+ echo -n $(cat ${SECRETS_DIR}/${FIT_NAME}-signature.tmp) | xargs printf "%02x" | \
112+ hex2bin > $SECRETS_DIR/$FIT_NAME-signature.raw
113+
114+ $OPENSSL dgst -sha256 -binary -out $SECRETS_DIR/$FIT_NAME-signature.hash \
115+ $SECRETS_DIR/$FIT_NAME-signature.raw || exit 1
116+
117+ gen_aes_key $KEY_DIR/${TEMP2_KEY_NAME}.key
118+
119+ enc_data $KEY_DIR/${TEMP2_KEY_NAME}.key \
120+ $SECRETS_DIR/$FIT_NAME-signature.hash \
121+ $SECRETS_DIR/$FIT_NAME-secret.enc \
122+ fit-secret
123+
124+ LD_LIBRARY_PATH=${LIBFDT_PATH} \
125+ $FDTPUT -c -p $FIT /fit-secrets/$CONFIG || exit 1
126+ LD_LIBRARY_PATH=${LIBFDT_PATH} \
127+ $FDTPUT $FIT /fit-secrets/$CONFIG algo -t s "sha256"
128+ LD_LIBRARY_PATH=${LIBFDT_PATH} \
129+ $FDTPUT $FIT /fit-secrets/$CONFIG data -t x \
130+ $(cat ${SECRETS_DIR}/${FIT_NAME}-secret.enc | bin2hex | \
131+ sed 's/ //g; s/.\{8\}/0x& /g; s/.$//g')
132+}
133+
134+# encrypt rootfs key
135+enc_rfsk() {
136+ echo "Encrypting rootfs key"
137+
138+ gen_aes_key $KEY_DIR/${ROOTFS_KEY_NAME}.key
139+ gen_aes_key $KEY_DIR/${TEMP1_KEY_NAME}.key
140+
141+ enc_data $KEY_DIR/${TEMP1_KEY_NAME}.key \
142+ $KEY_DIR/${ROOTFS_KEY_NAME}.key \
143+ $BUILD_DIR/${FIT_NAME}-rfsk.enc \
144+ k-rootfs
145+}
146+
147+while getopts "c:d:f:k:s:" OPTION
148+do
149+ case $OPTION in
150+ c ) CONFIG=$OPTARG;;
151+ d ) KEY_DIR=$OPTARG;;
152+ f ) FIT=$OPTARG;;
153+ k ) ROE_KEY=$OPTARG;;
154+ s ) BUILD_DIR=$OPTARG;;
155+ * ) echo "Invalid option passed to '$0' (options:$*)"
156+ usage;;
157+ esac
158+done
159+
160+if [ ! -d "${KEY_DIR}" ]; then
161+ echo "key directory not found"
162+ usage;
163+fi
164+
165+if [ ! -d "${BUILD_DIR}" ]; then
166+ echo "build directory not found"
167+ usage;
168+fi
169+
170+if [ -z "${FIT}" ]; then
171+ echo "FIT name is empty"
172+ usage;
173+fi
174+
175+if [ -z "${BIN}" ]; then
176+ echo "bin directory not found"
177+ exit 1
178+fi
179+
180+if [ ! -f "${ROE_KEY}".key ]; then
181+ echo "roe-key not found"
182+ usage;
183+fi
184+
185+OPENSSL=$BIN/openssl-3
186+AESGCM=$BIN/aesgcm
187+PERL=$BIN/perl
188+FDTGET=$BIN/fdtget
189+FDTPUT=$BIN/fdtput
190+
191+FIT_NAME=$(basename ${FIT} | sed "s/\.[^.]*$//g")
192+ROOTFS_KEY_NAME=${FIT_NAME}-rootfs-key
193+TEMP1_KEY_NAME=${FIT_NAME}-temp1-key
194+TEMP2_KEY_NAME=${FIT_NAME}-temp2-key
195+
196+if [ ! -z "${CONFIG}" ]; then
197+ gen_fit_secret;
198+else
199+ enc_rfsk;
200+fi
201diff --git a/scripts/fdt-patch-dm-crypt.sh b/scripts/fdt-patch-dm-crypt.sh
202new file mode 100755
203index 0000000..9ad87c7
204--- /dev/null
205+++ b/scripts/fdt-patch-dm-crypt.sh
206@@ -0,0 +1,26 @@
207+# !/bin/bash
208+FDTGET=$BIN/fdtget
209+FDTPUT=$BIN/fdtput
210+PERL=$BIN/perl
211+
212+FDT=$1
213+SUMMARY=$2
214+BOOTARGS=$(LD_LIBRARY_PATH=${LIBFDT_PATH} \
215+ ${FDTGET} ${FDT} /chosen bootargs | sed "s/\"*$/;/g")
216+DEVICE_PATH=$(echo -n ${BOOTARGS} | grep -o "root=/dev/dm-[0-9]\+" | \
217+ grep -o "/dev/dm-[0-9]\+")
218+DEVICE_NUM=$(echo -n ${DEVICE_PATH} | grep -o "[0-9]\+")
219+BOOTARGS=$(echo -n ${BOOTARGS} | \
220+ sed "s/root=\/dev\/dm-${DEVICE_NUM}/root=\/dev\/dm-$((DEVICE_NUM+1))/g")
221+DATABLOCKS_NUM=$(cat ${SUMMARY} | grep "Data blocks:" | grep -o "[0-9]\+")
222+CIPHER="aes-xts-plain64"
223+KEY=$(${PERL} -E 'say "0" x 64')
224+IV_OFFSET=0
225+OFFSET=0
226+
227+NEW_BOOTARGS=$( printf '%sdm-crypt,,,ro,0 %d crypt %s %s %d %s %d"' \
228+ "${BOOTARGS}" $((DATABLOCKS_NUM*8)) ${CIPHER} ${KEY} \
229+ ${IV_OFFSET} ${DEVICE_PATH} ${OFFSET} )
230+
231+LD_LIBRARY_PATH=${LIBFDT_PATH}
232+$FDTPUT $FDT /chosen bootargs -t s "${NEW_BOOTARGS}" || exit 1
233diff --git a/scripts/make-squashfs-encrypted.sh b/scripts/make-squashfs-encrypted.sh
234new file mode 100755
235index 0000000..9bb522b
236--- /dev/null
237+++ b/scripts/make-squashfs-encrypted.sh
238@@ -0,0 +1,37 @@
239+# !/bin/bash
240+ROOTFS=$1
241+ENCRYPTED_ROOTFS=$2
242+ROOTFS_KEY_DIR=$3
243+TARGET_DEVICE=$4
244+
245+if [ -z "${BIN}" ]; then
246+ echo "bin directory not found"
247+ exit 1
248+fi
249+
250+CRYPTSETUP=$BIN/cryptsetup
251+DEVICE_NAME=$(basename ${TARGET_DEVICE} | sed "s/\.[^.]*$//g")
252+ROOTFS_KEY=${ROOTFS_KEY_DIR}/${DEVICE_NAME}-rootfs-key.key
253+if [ ! -f "${ROOTFS}" ] || [ -z "${ENCRYPTED_ROOTFS}" ] ||
254+ [ ! -f "${ROOTFS_KEY}" ] || [ -z "${DEVICE_NAME}" ]; then
255+ exit 1
256+fi
257+
258+FILE_SIZE=`stat -c "%s" ${ROOTFS}`
259+BLOCK_SIZE=4096
260+DATA_BLOCKS=$((${FILE_SIZE} / ${BLOCK_SIZE}))
261+[ $((${FILE_SIZE} % ${BLOCK_SIZE})) -ne 0 ] && DATA_BLOCKS=$((${DATA_BLOCKS} + 1))
262+
263+# create container
264+dd if=/dev/zero of=$ENCRYPTED_ROOTFS bs=4096 count=$DATA_BLOCKS
265+
266+# mapping encrypted device
267+sudo $CRYPTSETUP open --type=plain --cipher=aes-xts-plain64 --key-size=256 \
268+ --key-file=$ROOTFS_KEY $ENCRYPTED_ROOTFS ${DEVICE_NAME}
269+
270+# encrypt squashfs
271+sudo dd if=$ROOTFS of=/dev/mapper/${DEVICE_NAME}
272+
273+# close mapping device
274+sudo $CRYPTSETUP close /dev/mapper/${DEVICE_NAME}
275+
276diff --git a/scripts/mkits.sh b/scripts/mkits.sh
277index 1c7f292..26bcf70 100755
278--- a/scripts/mkits.sh
279+++ b/scripts/mkits.sh
280@@ -17,7 +17,7 @@
281 usage() {
282 printf "Usage: %s -A arch -C comp -a addr -e entry" "$(basename "$0")"
283 printf " -v version -k kernel [-D name -n address -d dtb] -o its_file"
284- printf " [-s script] [-S key_name_hint] [-r ar_ver] [-R rootfs]"
285+ printf " [-s script] [-S key_name_hint] [-r ar_ver] [-R rootfs] [-m rfsk]"
286
287 printf "\n\t-A ==> set architecture to 'arch'"
288 printf "\n\t-C ==> set compression type 'comp'"
289@@ -33,13 +33,14 @@ usage() {
290 printf "\n\t-s ==> include u-boot script 'script'"
291 printf "\n\t-S ==> add signature at configurations and assign its key_name_hint by 'key_name_hint'"
292 printf "\n\t-r ==> set anti-rollback version to 'fw_ar_ver' (dec)"
293- printf "\n\t-R ==> specify rootfs file for embedding hash\n"
294+ printf "\n\t-R ==> specify rootfs file for embedding hash"
295+ printf "\n\t-m ==> include encrypted rootfs key'\n"
296 exit 1
297 }
298
299 FDTNUM=1
300
301-while getopts ":A:a:c:C:D:d:e:k:n:o:v:s:S:r:R:" OPTION
302+while getopts ":A:a:c:C:D:d:e:k:n:o:v:s:S:r:R:m:" OPTION
303 do
304 case $OPTION in
305 A ) ARCH=$OPTARG;;
306@@ -57,6 +58,7 @@ do
307 S ) KEY_NAME_HINT=$OPTARG;;
308 r ) AR_VER=$OPTARG;;
309 R ) ROOTFS_FILE=$OPTARG;;
310+ m ) ROOTFS_KEY=$OPTARG;;
311 * ) echo "Invalid option passed to '$0' (options:$*)"
312 usage;;
313 esac
314@@ -91,6 +93,19 @@ if [ -n "${DTB}" ]; then
315 FDT_PROP="fdt = \"fdt-$FDTNUM\";"
316 fi
317
318+# Conditionally create encrypted rootfs-key information
319+if [ -n "${ROOTFS_KEY}" ]; then
320+ RFSK_NODE="
321+ rfsk = <$(cat ${ROOTFS_KEY} | od -An -t x1 -w256 | sed 's/ //g; s/.\{8\}/0x& /g; s/.$//g')>;";
322+
323+ FIT_SECRET_NODE="
324+ fit-secrets {
325+ ${CONFIG} {
326+ };
327+ };
328+"
329+fi
330+
331 # Conditionally create rootfs hash information
332 if [ -f "${ROOTFS_FILE}" ]; then
333 ROOTFS_SIZE=$(stat -c %s ${ROOTFS_FILE})
334@@ -200,12 +215,15 @@ ${ROOTFS}
335 ${CONFIG} {
336 description = \"OpenWrt\";
337 ${FW_AR_VER}
338+${RFSK_NODE}
339 ${LOADABLES}
340 kernel = \"kernel-1\";
341 ${FDT_PROP}
342 ${SIGNATURE}
343 };
344 };
345+
346+${FIT_SECRET_NODE}
347 };"
348
349 # Write .its file to disk