V9.14.022.2026.06.10: Add boot attestation negative tests

This commit is contained in:
2026-06-10 23:13:36 +02:00
parent 42e2ae6b0e
commit eeecefc966
+228
View File
@@ -0,0 +1,228 @@
#!/bin/bash
# SPDX-Version: 3.0
# SPDX-FileCopyrightText: 2026; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
# SPDX-PackageName: CISS.debian.live.builder
set -Ceuo pipefail
declare ROOT_DIR=""
declare SHA512SUM=""
declare SHASUM=""
declare TMP_BASE=""
declare TMP_ROOT=""
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SHA512SUM="$(command -v sha512sum)"
SHASUM="$(command -v shasum || true)"
TMP_BASE="${TMPDIR:-/tmp}"
TMP_BASE="${TMP_BASE%/}"
TMP_ROOT="$(mktemp -d "${TMP_BASE}/ciss-boot-attestation.XXXXXXXX")"
cleanup() {
case "${TMP_ROOT}" in
"${TMP_BASE}/ciss-boot-attestation."*)
rm -rf -- "${TMP_ROOT}"
;;
*)
printf 'Refusing to clean unexpected test path: %s\n' "${TMP_ROOT}" >&2
return 1
;;
esac
}
trap cleanup EXIT
fail() {
printf 'FAIL: %s\n' "${1}" >&2
exit 1
}
prepare_checksum_hook() {
declare source_hook="${1}"
declare target_hook="${2}"
declare fault_mode="${3}"
declare test_bin="${4}"
declare test_tty="${5}"
declare test_runtime=""
test_runtime="$(dirname "${test_tty}")"
sed \
-e "s|/usr/bin/|${test_bin}/|g" \
-e "s|/run/ciss-|${test_runtime}/ciss-|g" \
-e "s|_TTY=\"/dev/tty8\"|_TTY=\"${test_tty}\"|" \
"${source_hook}" > "${target_hook}"
if [[ "${fault_mode}" == "unknown-state" ]]; then
sed \
-e 's/_RETURN_PGP="na"/_RETURN_PGP="unknown"/' \
-e 's/_RETURN_SHA="${?}"/_RETURN_SHA="unknown"/g' \
"${target_hook}" > "${target_hook}.new"
mv "${target_hook}.new" "${target_hook}"
fi
}
install_test_sha512sum() {
declare test_bin="${1}"
if printf '' | "${SHA512SUM}" -c >/dev/null 2>&1; then
ln -s "${SHA512SUM}" "${test_bin}/sha512sum"
elif [[ -n "${SHASUM}" ]]; then
printf '#!/bin/sh\nexec "%s" -a 512 "$@"\n' "${SHASUM}" > "${test_bin}/sha512sum"
chmod 0755 "${test_bin}/sha512sum"
else
fail "No SHA-512 tool with checksum verification support is available."
fi
}
run_checksum_case() {
declare source_hook="${1}"
declare case_name="${2}"
declare expected_status="${3}"
declare expected_message="${4}"
declare case_dir=""
declare hook_copy=""
declare output_file=""
declare test_bin=""
declare test_tty=""
declare source_id=""
declare fault_mode=""
declare panic_returns="false"
declare status=0
source_id="$(printf '%s' "${source_hook#"${ROOT_DIR}"/}" | tr '/' '_')"
case_dir="${TMP_ROOT}/${source_id}-${case_name}"
hook_copy="${case_dir}/0030-ciss-verify-checksums"
output_file="${case_dir}/output.log"
test_bin="${case_dir}/bin"
test_tty="${case_dir}/tty.log"
mkdir -p "${case_dir}" "${test_bin}"
: >| "${test_tty}"
case "${case_name}" in
valid)
install_test_sha512sum "${test_bin}"
printf 'trusted rootfs payload\n' > "${case_dir}/payload"
(cd "${case_dir}" && "${test_bin}/sha512sum" payload > sha512sum.txt)
;;
missing-manifest)
install_test_sha512sum "${test_bin}"
;;
unsupported-manifest)
install_test_sha512sum "${test_bin}"
printf 'unsupported\n' > "${case_dir}/md5sum.txt"
;;
failed-checksum)
install_test_sha512sum "${test_bin}"
printf 'trusted rootfs payload\n' > "${case_dir}/payload"
(cd "${case_dir}" && "${test_bin}/sha512sum" payload > sha512sum.txt)
printf 'tampered rootfs payload\n' >| "${case_dir}/payload"
;;
missing-tool)
install_test_sha512sum "${test_bin}"
printf 'trusted rootfs payload\n' > "${case_dir}/payload"
(cd "${case_dir}" && "${test_bin}/sha512sum" payload > sha512sum.txt)
rm -f "${test_bin}/sha512sum"
;;
unknown-state)
fault_mode="unknown-state"
panic_returns="true"
install_test_sha512sum "${test_bin}"
printf 'trusted rootfs payload\n' > "${case_dir}/payload"
(cd "${case_dir}" && "${test_bin}/sha512sum" payload > sha512sum.txt)
;;
*)
fail "Unknown checksum test case: ${case_name}"
;;
esac
prepare_checksum_hook "${source_hook}" "${hook_copy}" "${fault_mode}" "${test_bin}" "${test_tty}"
set +e
# shellcheck disable=SC2034,SC2329
(
set +C
CDLB_SCRIPT_FULL="${hook_copy}"
LIVE_BOOT_CMDLINE="verify-checksums=sha512"
LIVE_VERIFY_CHECKSUMS=""
log_begin_msg() { :; }
log_end_msg() { :; }
log_success_msg() { :; }
panic() {
printf 'PANIC: %s\n' "${1}" >&2
if [[ "${panic_returns}" == "true" ]]; then
return 0
fi
exit 97
}
sleep() { :; }
# shellcheck source=/dev/null
. "${hook_copy}"
Verify_checksums "${case_dir}"
) > "${output_file}" 2>&1
status="${?}"
set -e
[[ "${status}" -eq "${expected_status}" ]] || {
cat "${output_file}" >&2
fail "${source_hook} ${case_name}: expected status ${expected_status}, got ${status}"
}
grep -Fq "${expected_message}" "${output_file}" || {
cat "${output_file}" >&2
fail "${source_hook} ${case_name}: missing expected message '${expected_message}'"
}
}
test_rootfs_payload_tamper() {
declare case_dir="${TMP_ROOT}/rootfs-payload-tamper"
declare test_bin="${case_dir}/bin"
declare payload="${case_dir}/crypt_liveiso"
declare manifest="${case_dir}/ciss_rootfs.crypt.decrypted.sha512sum.txt"
declare build_hook="${ROOT_DIR}/config/hooks/live/zzzz_ciss_crypt_squash.hook.binary"
declare boot_hook="${ROOT_DIR}/config/includes.chroot/usr/lib/live/boot/0042_ciss_post_decrypt_attest"
mkdir -p "${case_dir}" "${test_bin}"
install_test_sha512sum "${test_bin}"
printf 'trusted selected rootfs mapper payload\n' > "${payload}"
"${test_bin}/sha512sum" "${payload}" > "${manifest}"
"${test_bin}/sha512sum" -c --strict --quiet "${manifest}"
printf 'tampered selected rootfs mapper payload\n' >> "${payload}"
if "${test_bin}/sha512sum" -c --strict --quiet "${manifest}" >/dev/null 2>&1; then
fail "Modified selected rootfs payload unexpectedly passed checksum verification."
fi
# shellcheck disable=SC2016
grep -Fq 'sha512sum "${MAPPER_DEV}" >| "${ROOTFS_ATTESTATION}"' "${build_hook}" || \
fail "Build hook does not generate the attestation from the decrypted mapper."
# shellcheck disable=SC2016
grep -Fq '/usr/bin/sha512sum -c --strict --quiet "${HASH_FILE}"' "${boot_hook}" || \
fail "Boot hook does not verify the selected rootfs payload with sha512sum -c."
# shellcheck disable=SC2016
grep -Fq '[ "${_ATTESTED_PAYLOAD}" != "${CDLB_MAPPER_DEV}" ]' "${boot_hook}" || \
fail "Boot hook does not require the manifest to target the selected rootfs payload."
}
declare -a CHECKSUM_HOOKS=(
"${ROOT_DIR}/config/includes.chroot/usr/lib/live/boot/0030-ciss-verify-checksums"
"${ROOT_DIR}/scripts/usr/lib/live/boot/0030-ciss-verify-checksums"
)
declare checksum_hook=""
for checksum_hook in "${CHECKSUM_HOOKS[@]}"; do
run_checksum_case "${checksum_hook}" "valid" 0 "Verification of [sha checksum] file successful"
run_checksum_case "${checksum_hook}" "missing-manifest" 97 "No supported checksum manifest found."
run_checksum_case "${checksum_hook}" "unsupported-manifest" 97 "No supported checksum manifest found."
run_checksum_case "${checksum_hook}" "failed-checksum" 97 "No supported checksum manifest was verified successfully."
run_checksum_case "${checksum_hook}" "missing-tool" 97 "No supported checksum verification tool was available."
run_checksum_case "${checksum_hook}" "unknown-state" 1 "Checksum verification ended in an unsupported state."
done
test_rootfs_payload_tamper
printf 'PASS: checksum verification fails closed and modified rootfs payloads fail attestation.\n'