developer | 23f9f0f | 2023-06-15 13:06:25 +0800 | [diff] [blame] | 1 | diff --git a/scripts/enc-rfsk.sh b/scripts/enc-rfsk.sh |
| 2 | new file mode 100755 |
| 3 | index 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 |
| 201 | diff --git a/scripts/fdt-patch-dm-crypt.sh b/scripts/fdt-patch-dm-crypt.sh |
| 202 | new file mode 100755 |
| 203 | index 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 |
| 233 | diff --git a/scripts/make-squashfs-encrypted.sh b/scripts/make-squashfs-encrypted.sh |
| 234 | new file mode 100755 |
| 235 | index 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 | + |
| 276 | diff --git a/scripts/mkits.sh b/scripts/mkits.sh |
| 277 | index 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 |