@@ -12,23 +12,6 @@ PROG="kryptik-install"
1212say () { printf ' %s: %s\n' " $PROG " " $* " ; }
1313die () { printf ' %s: FAILED: %s\n' " $PROG " " $* " >&2 ; exit 1; }
1414
15- # root.json is the medium's own record, not signed material: a rewritten
16- # record must be able to make the install fail and nothing else, so every
17- # field is checked for form before it is used, and what lands on the disk is
18- # verified against the root hash the signed kernel carries.
19- decimal_field () { # decimal_field NAME VALUE: a bounded decimal, or die
20- case " $2 " in ' ' |* [!0-9]* ) die " root.json: $1 is not a number" ;; esac
21- [ " ${# 2} " -le 15 ] || die " root.json: $1 is too large"
22- }
23- hex_field () { # hex_field NAME VALUE LENGTH: lowercase hex of that length, or die
24- case " $2 " in * [!0-9a-f]* ) die " root.json: $1 is not a hash" ;; esac
25- [ " ${# 2} " -eq " $3 " ] || die " root.json: $1 is not a hash"
26- }
27- # The root's dm-verity table from the signed command line, as
28- # "data_blocks hash_start_block root_hash salt"; empty when there is none.
29- verity_of () { # verity_of FILE
30- sed -n ' s/.* verity 1 [^ ]* [^ ]* 4096 4096 \([0-9][0-9]*\) \([0-9][0-9]*\) sha256 \([0-9a-f]\{64\}\) \([0-9a-f]*\) .*/\1 \2 \3 \4/p' " $1 " | head -1
31- }
3215# A slot may be made larger than this image needs, never smaller.
3316slot_size_ok () { # slot_size_ok ASKED NEEDED: both in MiB, or die
3417 case " $1 " in ' ' |0* |* [!0-9]* ) die " --slot-size takes a number of MiB" ;; esac
7255# --- every external tool, checked before the first write -------------------
7356missing=" "
7457for tool in sfdisk partx blockdev blkid cryptsetup veritysetup stty mkfs.ext4 dd sha256sum mount umount sync awk sed \
75- readlink lsblk head tail wc cmp cp mkdir stat tr cut basename mv mountpoint rmdir chmod rm cat sleep \
58+ grep readlink lsblk head tail wc cmp cp mkdir stat tr cut basename mv mountpoint rmdir chmod rm cat sleep \
7659 loadkeys chattr; do
7760 command -v " $tool " > /dev/null 2>&1 || missing=" ${missing} ${tool} "
7861done
@@ -92,6 +75,8 @@ part_dev() {
9275# are this system's own.
9376. /usr/libexec/kryptik/devices.sh
9477. /usr/libexec/kryptik/keyboard.sh
78+ # What the medium's root.json may be trusted for, shared with kryptik-recover.
79+ . /usr/libexec/kryptik/medium-root.sh
9580[ -z " $KEYBOARD " ] || kb_row " $KEYBOARD " > /dev/null || die " no keyboard layout named ${KEYBOARD} : kryptik keyboard lists them"
9681
9782# --- refuse anything that is not a disposable whole disk -------------------
@@ -184,6 +169,8 @@ case "$media" in
184169 mount -t iso9660 -o ro /dev/sr0 " $MNT_BASE /media" || die " could not mount the medium (/dev/sr0)"
185170 ESP_SRC=" $MNT_BASE /media/esp.img"
186171 [ -f " $ESP_SRC " ] || die " no esp.img on the medium"
172+ # For its kernels, read before anything is written.
173+ mount -t vfat -o ro,loop " $ESP_SRC " " $MNT_BASE /esp" || die " could not mount the medium's ESP image"
187174 ROOT_JSON=" $MNT_BASE /media/root.json"
188175 ROOT_SRC=/dev/sr0
189176 # The signed command line's linear table is "0 N linear /dev/sr0 START":
@@ -194,24 +181,11 @@ case "$media" in
194181 ;;
195182 * ) die " unknown medium type '${media} '" ;;
196183esac
197- [ -r " $ROOT_JSON " ] || die " no root.json on the medium"
198- jget () { sed -n " s/^ \" $1 \" : \" \{0,1\}\([^\" ,]*\)\" \{0,1\},\{0,1\}\$ /\1/p" " $ROOT_JSON " | head -1; }
199- ROOT_BYTES=" $( jget total_bytes) " ; ROOT_SHA=" $( jget sha256) " ; VERSION=" $( jget version) "
200- [ -n " $ROOT_BYTES " ] && [ -n " $ROOT_SHA " ] || die " root.json is incomplete"
201- decimal_field total_bytes " $ROOT_BYTES "
202- hex_field sha256 " $ROOT_SHA " 64
203- case " $VERSION " in * [!A-Za-z0-9._-]* ) die " root.json: version has characters a version cannot" ;; esac
204- # The record must name the root the signed kernel carries, and its size must
205- # hold that root and its hash tree without being absurd.
206- VERITY=" $( verity_of /proc/cmdline) "
207- [ -n " $VERITY " ] || die " could not read the root's verity table from the signed command line"
208- read -r V_BLOCKS V_HASH_START V_HASH V_SALT << EOF
209- $VERITY
210- EOF
211- [ " $( jget root_hash) " = " $V_HASH " ] || die " root.json names root hash $( jget root_hash) ; the signed kernel carries ${V_HASH} "
212- [ " $( jget data_blocks) " = " $V_BLOCKS " ] || die " root.json names $( jget data_blocks) data blocks; the signed kernel carries ${V_BLOCKS} "
213- [ " $ROOT_BYTES " -ge $(( (V_HASH_START + 1 ) * 4096 )) ] || die " root.json: total_bytes is smaller than the root and its hash tree"
214- [ " $ROOT_BYTES " -le $(( V_BLOCKS * 4096 + V_BLOCKS * 64 + 16777216 )) ] || die " root.json: total_bytes is larger than a root and its hash tree can be"
184+ medium_root " $ROOT_JSON " /proc/cmdline
185+ for s in a b; do
186+ kernel_names_root " $MNT_BASE /esp/EFI/kryptik/kryptik-$s .efi" \
187+ || die " the medium's kernel for slot $s does not carry the root hash its signed command line names; nothing was written"
188+ done
215189ESP_BYTES=" $( stat -c %s " $ESP_SRC " 2> /dev/null || blockdev --getsize64 " $ESP_SRC " ) "
216190[ -b " $ESP_SRC " ] && ESP_BYTES=" $( blockdev --getsize64 " $ESP_SRC " ) "
217191
@@ -318,10 +292,7 @@ say "reading kryptik-a back"
318292got=" $( dd if=" $P2 " bs=4M iflag=count_bytes count=" $ROOT_BYTES " status=none | sha256sum | cut -c1-64) "
319293[ " $got " = " $ROOT_SHA " ] || die " kryptik-a does not verify: wrote ${got} , the medium says ${ROOT_SHA} "
320294say " kryptik-a verifies (${got} )"
321- # The record can lie about itself; the kernel's root hash cannot.
322- veritysetup verify --no-superblock --hash=sha256 --data-block-size=4096 --hash-block-size=4096 \
323- --data-blocks=" $V_BLOCKS " --hash-offset=$(( V_HASH_START * 4096 )) --salt=" $V_SALT " " $P2 " " $P2 " " $V_HASH " \
324- || die " kryptik-a does not verify against the root hash the signed kernel carries"
295+ root_verifies " $P2 " || die " kryptik-a does not verify against the root hash the signed kernel carries"
325296say " kryptik-a verifies against the signed kernel's root hash"
326297say " clearing kryptik-b"
327298dd if=/dev/zero of=" $P3 " bs=1M count=4 conv=fsync status=none || die " clearing kryptik-b failed"
0 commit comments