V9.14.024.2026.06.11

Signed-off-by: Marc S. Weidner <msw@coresecret.dev>
This commit is contained in:
2026-06-11 17:11:22 +01:00
parent 9ef535554a
commit 97596fbcba
63 changed files with 767 additions and 200 deletions
@@ -1,4 +1,5 @@
#!/bin/bash
# shellcheck disable=SC2154
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-10-11; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
@@ -11,9 +12,10 @@
# SPDX-Security-Contact: security@coresecret.eu
set -Ceuo pipefail
# Final live-build binary hook for encrypted root filesystem packaging. Preallocate a LUKS2 container, formats it with the
# generated build secret, copies the generated filesystem.squashfs into the opened encrypted mapping, then closes the container,
# shreds the temporary LUKS secret, and removes the plaintext SquashFS from the ISO payload.
# Final live-build binary hook for encrypted root filesystem packaging. It creates and signs a deterministic attestation
# manifest for the final filesystem.squashfs byte stream, preallocates a LUKS2 container, formats it with the generated build
# secret, copies the generated filesystem.squashfs into the opened encrypted mapping, then closes the container, shreds the
# temporary LUKS secret, and removes the plaintext SquashFS from the ISO payload.
printf "\e[95m🧪 '%s' starting ... \e[0m\n" "${0}"
@@ -63,12 +65,120 @@ preallocate() {
# shellcheck disable=SC2034
readonly -f preallocate
declare ROOTFS="${VAR_HANDLER_BUILD_DIR}/binary/live/filesystem.squashfs"
declare LUKSFS="${VAR_HANDLER_BUILD_DIR}/binary/live/ciss_rootfs.crypt"
declare KEYFD=""
#######################################
# Create and sign the rootfs attestation manifest for the exact SquashFS payload copied into the LUKS mapper.
# Globals:
# VAR_SIGNING_KEY_FPR
# VAR_SIGNING_KEY_PASSFILE
# VAR_VERIFY_KEYRING
# Arguments:
# 1: Final SquashFS payload file
# 2: Manifest path below binary/live
# Returns:
# 0: on success
# 42: on failure
#######################################
create_attestation() {
declare rootfs_file="$1"
declare rootfs_attestation="$2"
declare rootfs_hash=""
declare rootfs_size=""
rootfs_size="$(stat -c%s -- "${rootfs_file}")"
rootfs_hash="$(sha512sum "${rootfs_file}")"
rootfs_hash="${rootfs_hash%% *}"
# The attested boundary is the final SquashFS byte stream before LUKS wrapping. The boot verifier reads exactly this many
# bytes from the decrypted mapper and intentionally excludes the LUKS allocation slack after the SquashFS payload.
cat << EOF >| "${rootfs_attestation}"
# CISS rootfs attestation manifest v1
# boundary: final filesystem.squashfs byte stream copied into /dev/mapper/crypt_liveiso
# rootfs-size-bytes: ${rootfs_size}
${rootfs_hash} ciss-rootfs.squashfs
EOF
chmod 0444 "${rootfs_attestation}"
gpg --batch --yes --pinentry-mode loopback --passphrase-file "${VAR_SIGNING_KEY_PASSFILE}" --local-user "${VAR_SIGNING_KEY_FPR}" \
--detach-sign --output "${rootfs_attestation}.sig" "${rootfs_attestation}"
chmod 0444 "${rootfs_attestation}.sig"
gpgv --keyring "${VAR_VERIFY_KEYRING}" "${rootfs_attestation}.sig" "${rootfs_attestation}"
printf "\e[92m[INFO] Rootfs attestation manifest created and verified: [%s]. \e[0m\n" "${rootfs_attestation}"
return 0
}
### Prevents accidental 'unset -f'.
# shellcheck disable=SC2034
readonly -f create_attestation
declare LUKSFS="${VAR_HANDLER_BUILD_DIR}/binary/live/ciss_rootfs.crypt"
declare ROOTFS="${VAR_HANDLER_BUILD_DIR}/binary/live/filesystem.squashfs"
declare ROOTFS_ATTESTATION="${VAR_HANDLER_BUILD_DIR}/binary/live/filesystem.squashfs.sha512sum.txt"
declare DM_LAB="crypt_liveiso"
declare DEVMAP="/dev/mapper/${DM_LAB}"
declare LUKS_KEY_FILE="${VAR_TMP_SECRET}/${VAR_LUKS_KEY:-luks.txt}"
declare KEYFD=""
# shellcheck disable=SC2155
declare -i VAR_ROOTFS_SIZE=$(stat -c%s -- "${ROOTFS}")
declare -i VAR_ROOTFS_SIZE="$(stat -c%s -- "${ROOTFS}")"
# shellcheck disable=SC2155
declare VAR_ROOTFS_HASH="$(LC_ALL=C sha512sum "${ROOTFS}")"
declare VAR_ROOTFS_HASH="${VAR_ROOTFS_HASH%% *}"
### Attestation Boundary
# - The attested boundary is the final SquashFS byte stream before LUKS wrapping.
# - The boot verifier reads exactly this many bytes from the decrypted mapper and intentionally excludes the LUKS allocation
# slack after the SquashFS payload.
printf "\e[95m🧪 Attestation of filesystem.squashfs ... \e[0m\n"
cat << EOF >| "${ROOTFS_ATTESTATION}"
# CISS.debian.live.builder Master ${VAR_VERSION}
# Attestation file for filesystem.squashfs Version 1.0.0
# Boundary : Final filesystem.squashfs byte stream copied into /dev/mapper/crypt_liveiso
# Bytes : Final filesystem.squashfs ${VAR_ROOTFS_SIZE}
${VAR_ROOTFS_HASH} filesystem.squashfs
EOF
chmod 0444 "${ROOTFS_ATTESTATION}"
if gpg --batch --yes --pinentry-mode loopback --passphrase-file "${VAR_SIGNING_KEY_PASSFILE}" --local-user "${VAR_SIGNING_KEY_FPR}" \
--detach-sign --output "${ROOTFS_ATTESTATION}.sig" "${ROOTFS_ATTESTATION}"; then
printf "\e[92m✅ [gpg of %s] successful. \e[0m\n" "${ROOTFS_ATTESTATION}"
else
printf "\e[91m❌ [gpg of %s] NOT successful. \e[0m\n" "${ROOTFS_ATTESTATION}"
return 42
fi
chmod 0444 "${ROOTFS_ATTESTATION}.sig"
if gpgv --keyring "${VAR_VERIFY_KEYRING}" "${ROOTFS_ATTESTATION}.sig" "${ROOTFS_ATTESTATION}"; then
printf "\e[92m✅ [gpgv of %s] successful. \e[0m\n" "${ROOTFS_ATTESTATION}.sig"
else
printf "\e[91m❌ [gpgv of %s] NOT successful. \e[0m\n" "${ROOTFS_ATTESTATION}.sig"
return 42
fi
if LC_ALL=C sha512sum -c --strict --quiet "${ROOTFS_ATTESTATION}"; then
printf "\e[92m✅ [LC_ALL=C sha512sum -c --strict --quiet of %s] successful. \e[0m\n" "${ROOTFS_ATTESTATION}"
else
printf "\e[91m❌ [LC_ALL=C sha512sum -c --strict --quiet of %s] NOT successful. \e[0m\n" "${ROOTFS_ATTESTATION}"
return 42
fi
printf "\e[92m✅ Attestation of filesystem.squashfs successful. \e[0m\n"
### Safety margin:
# - LUKS2-Header and Metadata
@@ -82,7 +192,7 @@ declare -i VAR_LUKSFS_SIZE=$(( ( (BASE_SIZE + ALIGN_BYTES - 1) / ALIGN_BYTES ) *
preallocate "${LUKSFS}" "${VAR_LUKSFS_SIZE}"
exec {KEYFD}<"${VAR_TMP_SECRET}/luks.txt"
exec {KEYFD}<"${LUKS_KEY_FILE}"
if [[ "${VAR_CDLB_INSIDE_RUNNER}" == "false" ]]; then
@@ -93,7 +203,7 @@ if [[ "${VAR_CDLB_INSIDE_RUNNER}" == "false" ]]; then
--iter-time 1000 \
--key-file "/proc/$$/fd/${KEYFD}" \
--key-size 512 \
--label crypt_liveiso \
--label "${DM_LAB}" \
--luks2-keyslots-size 16777216 \
--luks2-metadata-size 4194304 \
--pbkdf argon2id \
@@ -108,10 +218,11 @@ elif [[ "${VAR_CDLB_INSIDE_RUNNER}" == "true" ]]; then
cryptsetup luksFormat \
--batch-mode \
--cipher aes-xts-plain64 \
--integrity hmac-sha512 \
--iter-time 1000 \
--key-file "/proc/$$/fd/${KEYFD}" \
--key-size 512 \
--label crypt_liveiso \
--label "${DM_LAB}" \
--luks2-keyslots-size 16777216 \
--luks2-metadata-size 4194304 \
--pbkdf argon2id \
@@ -123,10 +234,10 @@ elif [[ "${VAR_CDLB_INSIDE_RUNNER}" == "true" ]]; then
fi
cryptsetup open --key-file "/proc/$$/fd/${KEYFD}" "${LUKSFS}" crypt_liveiso
cryptsetup open --key-file "/proc/$$/fd/${KEYFD}" "${LUKSFS}" "${DM_LAB}"
# shellcheck disable=SC2155
declare -i LUKS_FREE=$(blockdev --getsize64 /dev/mapper/crypt_liveiso)
declare -i LUKS_FREE=$(blockdev --getsize64 "${DEVMAP}")
declare -i SQUASH_FS="${VAR_ROOTFS_SIZE}"
if (( LUKS_FREE >= SQUASH_FS )); then
@@ -140,13 +251,13 @@ else
fi
dd if="${ROOTFS}" of=/dev/mapper/crypt_liveiso bs=8M status=progress conv=fsync
dd if="${ROOTFS}" of="${DEVMAP}" bs=8M status=progress conv=fsync
sync
cryptsetup close crypt_liveiso
cryptsetup close "${DM_LAB}"
exec {KEYFD}<&-
shred -fzu -n 5 -- "${VAR_TMP_SECRET}/luks.txt"
shred -fzu -n 5 -- "${LUKS_KEY_FILE}"
rm -f -- "${ROOTFS}"
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.022.2026.06.10
# Version Master V9.14.024.2026.06.11
[git.coresecret.dev]:42842 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGQA107AVmg1D/jnyXiqbPf38zQRl8s3c+PM1zbfpeQl
[git.coresecret.dev]:42842 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDYD9ysmMWZlejUnxu0qOzeWcIYezoFLbYdo6ffGUL5kqOBAYb+5CF4bJLUpA93XFYVF+TbrcMV1yJh6JaHFL0VU5CvgAzruCeedx0c4qUV6lWcJUGNk5K0yb9n2Wosdy6F/zTOxL9KXBt/TV+cscsen2Dahvx0ctMKgNbu+vvUcWxHf9lOkbYoF/uA/nW5CVXy5XUPVUDFUhEeKXL85+6gid5AEMfYT8aRl5YDGvo1iMBmBYOljN4S7MnRe14qbAZG0GDGvF22eHbSU2pILcFIjc2Lo/S5Ox/MJpbLAqpFlLPTKgr6F7yVwfNMSNwl05ysUOZfrQKSXzCU6+lfqKYCwemLALyG/n1ernpp7/8W/2RYoz3fd+TQyfhW++rx3yUHpYCkTv9A4LRYZYGSAWKMHSBEYq3EcATQUxQi0xpwmcR+u0uC9F9eta5Bim+sBZD6F2hgPJ5xgYT8LFm880g1YadAwBoD4TAkqSvl+jYW0VA2GH9CknKHJ36gc/X4eeUHDC1Hf/E8M5RBj4D6NuHfeVRik/ahHmoCqKQUW7VU/EBsWFsngDiLEHcV71iMtWiUddWOHwoAPHIzn6p9HTeLCxTwsPMG5UDGK/S9HUozqDXxexRtqbcFa7DWuzRvZ1bcZ2VQsaafuzKCkkc4NjC7h1wssel7q9aeYPFg+1vS6Q==
+1 -1
View File
@@ -9,7 +9,7 @@
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.022.2026.06.10
# Version Master V9.14.024.2026.06.11
### https://www.ssh-audit.com/
### ssh -Q cipher | cipher-auth | compression | kex | kex-gss | key | key-cert | key-plain | key-sig | mac | protocol-version | sig
@@ -11,7 +11,7 @@
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu
# Version Master V9.14.022.2026.06.10
# Version Master V9.14.024.2026.06.11
### https://docs.kernel.org/
### https://github.com/a13xp0p0v/kernel-hardening-checker/
@@ -10,7 +10,7 @@
# SPDX-PackageName: CISS.debian.live.builder
# SPDX-Security-Contact: security@coresecret.eu
declare -gr VERSION="Master V9.14.022.2026.06.10"
declare -gr VERSION="Master V9.14.024.2026.06.11"
### VERY EARLY CHECK FOR DEBUGGING
if [[ $* == *" --debug "* ]]; then
+1 -1
View File
@@ -112,4 +112,4 @@ d-i preseed/late_command string sh /preseed/.ash/3_di_preseed_late_command.sh
# Please consider donating to my work at: https://coresecret.eu/spenden/
###########################################################################################
# Written by: ./preseed_hash_generator.sh Version: Master V9.14.022.2026.06.10 at: 10:18:37.9542
# Written by: ./preseed_hash_generator.sh Version: Master V9.14.024.2026.06.11 at: 10:18:37.9542
@@ -15,12 +15,14 @@
# SPDX-Security-Contact: security@coresecret.eu
# Module summary:
# This live-boot component implements the verify-checksums mode for the mounted live medium.
# It reads the live-boot command line to decide whether checksum verification is enabled and which digests to accept.
# It locates the pinned CISS GPG key material on the live medium, optionally verifies this script's signed hash,
# optionally verifies signed checksum files, and checks the first matching checksum manifest with the matching digest tool. It
# writes detailed checksum output to the verification TTY. It panics instead of continuing boot when integrity or
# authenticity verification fails.
# This live-boot component implements verify-checksums mode for the mounted live medium.
# It reads the live-boot command line to decide whether checksum verification is enabled, which digests to accept, and
# whether checksum signature verification is required. When signature verification is enabled, it requires to be pinned CISS GPG
# key material from the live medium, verifies this script's signed SHA-512 hash, and verifies the selected checksum manifest
# signature before accepting checksum results. It checks the first supported checksum manifest with an available matching digest
# tool and writes detailed checksum command output to the verification TTY when checksum execution runs. It fails closed by
# panicking on missing manifests, missing digest tools, empty manifests, failed signatures, failed checksums, or unknown
# verification states.
### Modified Version of the original file:
### https://salsa.debian.org/live-team/live-boot 'components/0030-ciss-verify-checksums'
@@ -87,11 +89,26 @@ Verify_checksums() {
_CHECKSUM_LOG=""
_CHECKSUM_LOG_DIR="${LIVE_VERIFY_CHECKSUMS_LOG_DIR:-/run}"
_KEYFILE=""
_MANIFEST_FOUND="false"
_MP=""
_RETURN_PGP=""
_RETURN_SHA=""
_TOOL_FOUND="false"
_VERIFICATION_EXECUTED="false"
_VERIFICATION_SUCCEEDED="false"
### Parse commandline arguments ----------------------------------------------------------------------------------------------
# shellcheck disable=SC2154
for _PARAMETER in ${LIVE_BOOT_CMDLINE}; do
case "${_PARAMETER}" in
@@ -148,6 +165,14 @@ Verify_checksums() {
done
if [ "${LIVE_VERIFY_CHECKSUMS_SIGNATURES}" = "true" ] && [ -z "${_KEYFILE}" ]; then
log_er "No pinned GPG key file found while checksum signature verification is enabled."
sleep 8
panic "[FATAL] No pinned GPG key file found while checksum signature verification is enabled."
fi
# shellcheck disable=SC2164
cd "${_MOUNTPOINT}"
@@ -244,10 +269,14 @@ Verify_checksums() {
if [ -e "${_CHECKSUM}" ]; then
_MANIFEST_FOUND="true"
log_in "Found: [${_CHECKSUM}] ..."
if [ -e "/usr/bin/${_DIGEST}sum" ]; then
_TOOL_FOUND="true"
log_in "Found: [/usr/bin/${_DIGEST}sum] ..."
if [ "${LIVE_VERIFY_CHECKSUMS_SIGNATURES}" = "true" ]; then
@@ -275,8 +304,15 @@ Verify_checksums() {
fi
# shellcheck disable=SC2312
_CHECKSUM_LOG="/run/ciss-${_DIGEST}sum-check.log"
if grep -v '^#' "${_CHECKSUM}" | LC_ALL=C /usr/bin/"${_DIGEST}"sum -c > "${_CHECKSUM_LOG}" 2>&1; then
_CHECKSUM_LOG="${_CHECKSUM_LOG_DIR}/ciss-${_DIGEST}sum-check.log"
_VERIFICATION_EXECUTED="true"
if ! grep -v '^#' "${_CHECKSUM}" | grep -q '[^[:space:]]'; then
_RETURN_SHA="254"
: > "${_CHECKSUM_LOG}"
log_er "Checksum manifest has no checksum entries: [${_CHECKSUM}]"
elif grep -v '^#' "${_CHECKSUM}" | LC_ALL=C /usr/bin/"${_DIGEST}"sum -c > "${_CHECKSUM_LOG}" 2>&1; then
_RETURN_SHA="${?}"
cat "${_CHECKSUM_LOG}" > "${_TTY}"
@@ -294,6 +330,12 @@ Verify_checksums() {
fi
if { [ "${_RETURN_PGP}" = "0" ] || [ "${_RETURN_PGP}" = "na" ]; } && [ "${_RETURN_SHA}" = "0" ]; then
_VERIFICATION_SUCCEEDED="true"
fi
# Stop after the first verification.
break 2
@@ -313,6 +355,36 @@ Verify_checksums() {
log_end_msg
printf "\n"
if [ "${_MANIFEST_FOUND}" != "true" ]; then
log_er "No supported checksum manifest found. Checksum verification is fail-closed."
sleep 8
panic "[FATAL] No supported checksum manifest found. Checksum verification is fail-closed."
fi
if [ "${_TOOL_FOUND}" != "true" ]; then
log_er "Checksum manifest found, but no supported checksum tool is available. Checksum verification is fail-closed."
sleep 8
panic "[FATAL] Checksum manifest found, but no supported checksum tool is available. Checksum verification is fail-closed."
fi
if [ "${_VERIFICATION_EXECUTED}" != "true" ]; then
log_er "Checksum verification was not executed. Checksum verification is fail-closed."
sleep 8
panic "[FATAL] Checksum verification was not executed. Checksum verification is fail-closed."
fi
if [ "${_VERIFICATION_SUCCEEDED}" != "true" ]; then
log_er "[FATAL] Checksum verification did not complete successfully. Evaluating fail-closed failure state."
fi
case "${_RETURN_PGP},${_RETURN_SHA}" in
"0,0")
@@ -345,6 +417,12 @@ Verify_checksums() {
panic "Verification of [sha checksum] file failed."
;;
*)
log_er "Unknown checksum verification state: [${_RETURN_PGP:-unset},${_RETURN_SHA:-unset}]."
sleep 8
panic "[FATAL] Unknown checksum verification state. Checksum verification is fail-closed."
;;
esac
}
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
@@ -16,18 +16,27 @@
# Module summary:
# - Runs after the encrypted live root filesystem has been decrypted.
# - Requires the pinned public key, attestation hash file, and detached signature to exist as readable, non-empty regular files
# inside the decrypted rootfs.
# - Verifies the attestation signature with gpgv against the pinned key material.
# - Confirms that the signature fingerprint matches the build-time expected rootfs fingerprint and panics on missing, malformed,
# or mismatched evidence.
_SAVED_SET_OPTS="$(set +o)"
# - Requires the pinned public key, external rootfs attestation manifest, and detached signature to exist as readable,
# non-empty regular files.
# - Verifies the attestation signature with gpgv against the pinned key material and expected signer fingerprint.
# - Verifies the exact final SquashFS byte stream copied into the decrypted LUKS mapper. The signed manifest provides both the
# SHA-512 digest and the exact byte length; allocation slack after that SquashFS payload is intentionally out of scope.
# - Panics on missing, malformed, unauthentic, or mismatched evidence.
set -eu
printf "\e[95m[INFO] Starting : [/usr/lib/live/boot/0042_ciss_post_decrypt_attest] \n\e[0m"
### Check panic command availability -------------------------------------------------------------------------------------------
if ! command -v panic >/dev/null 2>&1; then
panic() {
printf '\e[91m[FATAL] %s \n\e[0m' "${*}" >&2
exit 1
}
fi
### Declare variables ----------------------------------------------------------------------------------------------------------
### Will be replaced at build time:
@@ -36,10 +45,13 @@ export CDLB_EXP_CA_FPR="@EXP_CA_FPR@"
### Name of the top-level dm-crypt mapping (e.g., cryptsetup --label): zzzz_ciss_crypt_squash.hook.binary ----------------------
export CDLB_MAPPER_NAME="${CDLB_MAPPER_NAME:-crypt_liveiso}"
export CDLB_MAPPER_DEV="${CDLB_MAPPER_DEV:-/dev/mapper/${CDLB_MAPPER_NAME}}"
export CDLB_MNT_MEDIUM="${CDLB_MNT_MEDIUM:-/run/live/medium}"
### Attestation file locations inside decrypted rootfs. ------------------------------------------------------------------------
CDLB_ATTEST_FPR_SHA="${CDLB_ATTEST_FPR_SHA:-/root/root/.ciss/attestation/${CDLB_EXP_FPR}.gpg.sha512sum.txt}"
CDLB_ATTEST_FPR_SIG="${CDLB_ATTEST_FPR_SIG:-/root/root/.ciss/attestation/${CDLB_EXP_FPR}.gpg.sha512sum.txt.sig}"
### Locations of the attestation file of filesystem.squashfs on the verified live medium. --------------------------------------
CDLB_ROOTFS_ATTEST_MANIFEST="${CDLB_ROOTFS_ATTEST_MANIFEST:-${CDLB_MNT_MEDIUM}/live/filesystem.squashfs.sha512sum.txt}"
CDLB_ROOTFS_ATTEST_SIGNATURE="${CDLB_ROOTFS_ATTEST_SIGNATURE:-${CDLB_ROOTFS_ATTEST_MANIFEST}.sig}"
CDLB_ROOTFS_ATTEST_CHECK="${CDLB_ROOTFS_ATTEST_CHECK:-/run/ciss-rootfs-attestation.sha512sum}"
CDLB_KEY_DIR="${CDLB_KEY_DIR:-/etc/ciss/keys}"
### Declare functions ----------------------------------------------------------------------------------------------------------
@@ -123,15 +135,162 @@ require_attestation_file() {
return 0
}
HASH_FILE="${CDLB_ATTEST_FPR_SHA}"
SIGN_FILE="${CDLB_ATTEST_FPR_SIG}"
#######################################
# Validate the decrypted rootfs payload device.
# Globals:
# None
# Arguments:
# 1: Absolute payload device path
# Returns:
# 0: on success
#######################################
require_rootfs_payload_device() {
artifact_path="${1}"
if [ ! -e "${artifact_path}" ]; then
log_er "0042() : Rootfs payload device missing: [${artifact_path}]"
panic "0042() : Rootfs payload device missing: [${artifact_path}]"
fi
if [ -L "${artifact_path}" ] || { [ ! -b "${artifact_path}" ] && [ ! -f "${artifact_path}" ]; }; then
log_er "0042() : Rootfs payload must be a block device or regular test fixture: [${artifact_path}]"
panic "0042() : Rootfs payload must be a block device or regular test fixture: [${artifact_path}]"
fi
if [ ! -r "${artifact_path}" ]; then
log_er "0042() : Rootfs payload is not readable: [${artifact_path}]"
panic "0042() : Rootfs payload is not readable: [${artifact_path}]"
fi
return 0
}
#######################################
# Stream exactly the attested SquashFS payload bytes from the decrypted mapper.
# Globals:
# None
# Arguments:
# 1: Payload device or regular test fixture
# 2: Exact payload byte count
# Returns:
# 0: on success
#######################################
stream_rootfs_payload() {
payload_device="${1}"
payload_size="${2}"
block_size=1048576
full_blocks=$((payload_size / block_size))
remainder=$((payload_size % block_size))
remainder_offset=$((full_blocks * block_size))
if [ "${full_blocks}" -gt 0 ]; then
dd if="${payload_device}" bs="${block_size}" count="${full_blocks}" 2>/dev/null || return 1
fi
if [ "${remainder}" -gt 0 ]; then
dd if="${payload_device}" bs=1 skip="${remainder_offset}" count="${remainder}" 2>/dev/null || return 1
fi
return 0
}
#######################################
# Verify the attested SquashFS payload hash against the decrypted mapper bytes.
# Globals:
# CDLB_ROOTFS_ATTEST_CHECK
# Arguments:
# 1: Manifest path
# 2: Payload device path
# Returns:
# 0: on success
#######################################
verify_rootfs_payload() {
manifest_path="${1}"
payload_device="${2}"
payload_size=""
payload_hash=""
payload_size="$(awk -F': ' '/^# rootfs-size-bytes: /{print $2; exit}' "${manifest_path}")"
payload_hash="$(awk '($0 !~ /^#/ && NF >= 2){print $1; exit}' "${manifest_path}")"
case "${payload_size}" in
""|*[!0-9]*)
log_er "0042() : Rootfs attestation manifest has invalid payload size."
panic "0042() : Rootfs attestation manifest has invalid payload size."
;;
esac
if [ "${payload_size}" -le 0 ]; then
log_er "0042() : Rootfs attestation manifest has empty payload size."
panic "0042() : Rootfs attestation manifest has empty payload size."
fi
case "${payload_hash}" in
""|*[!0123456789abcdefABCDEF]*)
log_er "0042() : Rootfs attestation manifest has invalid SHA-512 payload hash."
panic "0042() : Rootfs attestation manifest has invalid SHA-512 payload hash."
;;
esac
if [ "${#payload_hash}" -ne 128 ]; then
log_er "0042() : Rootfs attestation manifest SHA-512 payload hash has invalid length."
panic "0042() : Rootfs attestation manifest SHA-512 payload hash has invalid length."
fi
if ! printf '%s -\n' "${payload_hash}" > "${CDLB_ROOTFS_ATTEST_CHECK}"; then
log_er "0042() : Failed to prepare transient rootfs payload checksum file."
panic "0042() : Failed to prepare transient rootfs payload checksum file."
fi
chmod 0600 "${CDLB_ROOTFS_ATTEST_CHECK}" 2>/dev/null || :
log_in "0042() : Verifying exact SquashFS payload bytes from: [${payload_device}]"
# stream_rootfs_payload may be evaluated in a pipeline here; sha512sum -c is the fail-closed authority for truncated or
# tampered payload bytes.
# shellcheck disable=SC2310
if ! stream_rootfs_payload "${payload_device}" "${payload_size}" | /usr/bin/sha512sum -c "${CDLB_ROOTFS_ATTEST_CHECK}"; then
log_er "0042() : Rootfs payload SHA-512 verification failed."
panic "0042() : Rootfs payload SHA-512 verification failed."
fi
log_ok "0042() : Rootfs payload SHA-512 verification successful."
return 0
}
HASH_FILE="${CDLB_ROOTFS_ATTEST_MANIFEST}"
SIGN_FILE="${CDLB_ROOTFS_ATTEST_SIGNATURE}"
KEYFILE="${CDLB_KEY_DIR}/${CDLB_EXP_FPR}.gpg"
require_attestation_file "Public key" "${KEYFILE}"
require_attestation_file "Attestation data" "${HASH_FILE}"
require_attestation_file "Attestation signature" "${SIGN_FILE}"
require_attestation_file "Public key" "${KEYFILE}"
require_attestation_file "Rootfs attestation manifest" "${HASH_FILE}"
require_attestation_file "Rootfs attestation signature" "${SIGN_FILE}"
require_rootfs_payload_device "${CDLB_MAPPER_DEV}"
log_in "0042() : Verifying rootfs attestation with 'gpgv' and inside LUKS encrypted rootfs pinned GPG FPR."
log_in "0042() : Verifying rootfs attestation manifest with 'gpgv' and pinned GPG FPR."
if ! _STATUS="$(/usr/bin/gpgv --keyring "${KEYFILE}" --status-fd 1 "${SIGN_FILE}" "${HASH_FILE}" 2>&1)"; then
@@ -163,7 +322,7 @@ else
fi
eval "${_SAVED_SET_OPTS}"
verify_rootfs_payload "${HASH_FILE}" "${CDLB_MAPPER_DEV}"
printf "\e[92m[INFO] Successfully applied : [/usr/lib/live/boot/0042_ciss_post_decrypt_attest] \n\e[0m"