V8.13.408.2025.11.13
Signed-off-by: Marc S. Weidner <msw@coresecret.dev>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
#!/bin/sh
|
||||
# bashsupport disable=BP5007
|
||||
# shellcheck disable=SC2249
|
||||
# shellcheck shell=sh
|
||||
|
||||
# SPDX-Version: 3.0
|
||||
# SPDX-CreationInfo: 2025-11-12; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
|
||||
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
# SPDX-FileType: SOURCE
|
||||
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
|
||||
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
|
||||
# SPDX-PackageName: CISS.debian.live.builder
|
||||
# SPDX-Security-Contact: security@coresecret.eu
|
||||
|
||||
# Purpose: Pre-create constrained tmpfs for OverlayFS upper/work before live-boot mounts overlay.
|
||||
# Phase : premount (executed by live-boot inside the initramfs).
|
||||
|
||||
set -eu
|
||||
|
||||
### Phase gate: run only in the intended live-boot phase -----------------------------------------------------------------------
|
||||
PHASE="${1:-}"
|
||||
|
||||
case "${PHASE}" in
|
||||
|
||||
premount)
|
||||
;; ### Continue.
|
||||
*)
|
||||
exit 0 ### Do nothing in other phases.
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
printf "\e[95m[INFO] Starting: [/usr/lib/live/boot/0022-ciss-overlay-tmpfs.sh] ... \n\e[0m"
|
||||
|
||||
### Declare variables ----------------------------------------------------------------------------------------------------------
|
||||
OVERLAY_BASE="/run/live/overlay"
|
||||
UPPER="${OVERLAY_BASE}/upper"
|
||||
WORK="${OVERLAY_BASE}/work"
|
||||
|
||||
### Size policy: hard ceiling to mitigate RAM-filling DoS; tune to your ISO profile.
|
||||
: "${CDLB_OVERLAY_TMPFS_SIZE:=70%}"
|
||||
|
||||
### Create a base dir with restrictive perms.
|
||||
# shellcheck disable=SC2174
|
||||
mkdir -p -m 0700 "${OVERLAY_BASE}"
|
||||
|
||||
### Mount dedicated tmpfs with strict flags; 'noexec' here blocks accidental execs from the raw tmpfs path.
|
||||
mount -t tmpfs -o "size=${CDLB_OVERLAY_TMPFS_SIZE},mode=0700,nosuid,nodev,noexec" tmpfs "${OVERLAY_BASE}"
|
||||
|
||||
# Prepare upper/work with tight perms.
|
||||
# shellcheck disable=SC2174
|
||||
mkdir -p -m 0700 "${UPPER}" "${WORK}"
|
||||
|
||||
printf "\e[92m[INFO] Successfully applied: [/usr/lib/live/boot/0022-ciss-overlay-tmpfs.sh] \n\e[0m"
|
||||
|
||||
exit 0
|
||||
|
||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||
170
config/includes.chroot/usr/lib/live/boot/0024-ciss-crypt-squash
Normal file
170
config/includes.chroot/usr/lib/live/boot/0024-ciss-crypt-squash
Normal file
@@ -0,0 +1,170 @@
|
||||
#!/bin/sh
|
||||
# bashsupport disable=BP5007
|
||||
# shellcheck disable=SC2249
|
||||
# shellcheck shell=sh
|
||||
|
||||
# SPDX-Version: 3.0
|
||||
# SPDX-CreationInfo: 2025-11-12; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
|
||||
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
# SPDX-FileType: SOURCE
|
||||
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
|
||||
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
|
||||
# SPDX-PackageName: CISS.debian.live.builder
|
||||
# SPDX-Security-Contact: security@coresecret.eu
|
||||
|
||||
# Purpose: Open /live/ciss_rootfs.crypt (LUKS) and present its SquashFS as /run/live/rootfs
|
||||
# Phase : premount (executed by live-boot inside the initramfs)
|
||||
|
||||
set -eu
|
||||
|
||||
### Phase gate: run only in the intended live-boot phase -----------------------------------------------------------------------
|
||||
PHASE="${1:-}"
|
||||
|
||||
case "${PHASE}" in
|
||||
|
||||
premount)
|
||||
;; ### Continue.
|
||||
*)
|
||||
exit 0 ### Do nothing in other phases.
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
printf "\e[95m[INFO] Starting: [/usr/lib/live/boot/0024-ciss-crypt-squash] ... \n\e[0m"
|
||||
|
||||
#######################################
|
||||
# Premount logging helper.
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# *: String to log.
|
||||
#######################################
|
||||
log() {
|
||||
msg="$*"
|
||||
if [ -w /dev/kmsg ]; then
|
||||
printf '<6>%s: %s\n' '0024-ciss-crypt-squash' "${msg}" > /dev/kmsg
|
||||
else
|
||||
printf '%s: %s\n' '0024-ciss-crypt-squash' "${msg}"
|
||||
fi
|
||||
}
|
||||
|
||||
### Declare variables ----------------------------------------------------------------------------------------------------------
|
||||
CDLB_LUKS_FS="/live/ciss_rootfs.crypt"
|
||||
CDLB_ISO_LABEL="CISS.debian.live"
|
||||
MNT_MEDIUM="/run/live/medium"
|
||||
MNT_ROOTFS="/run/live/rootfs"
|
||||
_PARAMETER=""
|
||||
_dev=""
|
||||
|
||||
for _PARAMETER in ${LIVE_BOOT_CMDLINE}; do
|
||||
|
||||
case "${_PARAMETER}" in
|
||||
|
||||
ciss_crypt_path=*) CDLB_LUKS_FS="${_PARAMETER#ciss_crypt_path=}";;
|
||||
ciss_iso_label=* ) CDLB_ISO_LABEL="${_PARAMETER#ciss_iso_label=}";;
|
||||
|
||||
esac
|
||||
|
||||
done
|
||||
|
||||
mkdir -p "${MNT_MEDIUM}" "${MNT_ROOTFS}"
|
||||
|
||||
### Mount the live medium (ISO) read-only, unless already mounted --------------------------------------------------------------
|
||||
if ! mountpoint -q "${MNT_MEDIUM}"; then
|
||||
|
||||
if [ -n "${CDLB_ISO_LABEL}" ] && [ -e "/dev/disk/by-label/${CDLB_ISO_LABEL}" ]; then
|
||||
|
||||
mount -r -t iso9660 "/dev/disk/by-label/${CDLB_ISO_LABEL}" "${MNT_MEDIUM}" 2>/dev/null \
|
||||
|| mount -r -t udf "/dev/disk/by-label/${CDLB_ISO_LABEL}" "${MNT_MEDIUM}" 2>/dev/null \
|
||||
|| log "could not mount label=${CDLB_ISO_LABEL} (iso9660/udf)"
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if ! mountpoint -q "${MNT_MEDIUM}"; then
|
||||
|
||||
### Fallback scan (covers SR drives and loop-mounted ISOs that udev exposed).
|
||||
for _dev in /dev/sr* /dev/cdrom /dev/disk/by-label/*; do
|
||||
|
||||
### Skip non-block entries early.
|
||||
[ -b "${_dev}" ] || continue
|
||||
|
||||
### Try ISO9660 first, then UDF; only unmount on failure
|
||||
if mount -r -t iso9660 "${_dev}" "${MNT_MEDIUM}" 2>/dev/null \
|
||||
|| mount -r -t udf "${_dev}" "${MNT_MEDIUM}" 2>/dev/null
|
||||
then
|
||||
|
||||
mountpoint -q "${MNT_MEDIUM}" 2>/dev/null && break
|
||||
|
||||
else
|
||||
|
||||
umount "${MNT_MEDIUM}" 2>/dev/null || true
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
if ! mountpoint -q "${MNT_MEDIUM}"; then
|
||||
|
||||
log "no live medium mounted – defer to default live-boot path"
|
||||
exit 0
|
||||
|
||||
fi
|
||||
|
||||
### Locate the encrypted root container on the medium. -------------------------------------------------------------------------
|
||||
if [ ! -f "${MNT_MEDIUM}/${CDLB_LUKS_FS}" ]; then
|
||||
|
||||
log "encrypted root not found at ${MNT_MEDIUM}/${CDLB_LUKS_FS}"
|
||||
exit 0
|
||||
|
||||
fi
|
||||
|
||||
### Create/read FIFO compatible with cryptsetup-initramfs (if present). This allows 'cryptroot-unlock' to feed the passphrase
|
||||
### over SSH (dropbear).
|
||||
mkdir -p /lib/cryptsetup
|
||||
[ -p /lib/cryptsetup/passfifo ] || mkfifo /lib/cryptsetup/passfifo
|
||||
|
||||
### Attach a loop device read-only to the encrypted file. ----------------------------------------------------------------------
|
||||
LOOP="$(losetup -f --show -r "${MNT_MEDIUM}/${CDLB_LUKS_FS}")" || { log "losetup failed"; exit 42; }
|
||||
|
||||
### Try to open the LUKS container, first via FIFO (SSH unlock), then interactively. -------------------------------------------
|
||||
attempts=0
|
||||
while true; do
|
||||
|
||||
attempts=$((attempts+1))
|
||||
echo "Unlock '${CDLB_LUKS_FS}' (try ${attempts}): use 'cryptroot-unlock' over SSH or enter on console" >/dev/console 2>/dev/null || true
|
||||
|
||||
## Non-blocking read from FIFO (Dropbear and cryptroot-unlock path).
|
||||
if timeout 5 cat /lib/cryptsetup/passfifo | cryptsetup open --type luks --readonly "${LOOP}" crypt_liveiso --key-file - 2>/dev/null; then
|
||||
|
||||
break
|
||||
|
||||
fi
|
||||
|
||||
### Interactive fallback on the console.
|
||||
if cryptsetup open --type luks --readonly "${LOOP}" crypt_liveiso; then
|
||||
|
||||
break
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
### Mount the decrypted payload as SquashFS under '/run/live/rootfs'. ----------------------------------------------------------
|
||||
mount -r -t squashfs /dev/mapper/crypt_liveiso "${MNT_ROOTFS}" || { log "mount squashfs failed"; exit 1; }
|
||||
|
||||
### Ensure live-boot keeps using our medium (bind-mount for consistency). ------------------------------------------------------
|
||||
mount --bind "${MNT_MEDIUM}" "${MNT_MEDIUM}" 2>/dev/null || true
|
||||
|
||||
log "encrypted squashfs is mounted at ${MNT_ROOTFS} (device=/dev/mapper/crypt_liveiso)"
|
||||
|
||||
printf "\e[92m[INFO] Successfully applied: [/usr/lib/live/boot/0024-ciss-crypt-squash] \n\e[0m"
|
||||
|
||||
exit 0
|
||||
|
||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
# bashsupport disable=BP5007
|
||||
# shellcheck disable=SC2249
|
||||
# shellcheck shell=sh
|
||||
|
||||
# SPDX-Version: 3.0
|
||||
# SPDX-CreationInfo: 2025-11-12; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
|
||||
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
# SPDX-FileType: SOURCE
|
||||
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
|
||||
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
|
||||
# SPDX-PackageName: CISS.debian.live.builder
|
||||
# SPDX-Security-Contact: security@coresecret.eu
|
||||
|
||||
# Purpose: Enforce early sysctls before services start.
|
||||
# Phase : premount (executed by live-boot inside the initramfs).
|
||||
|
||||
set -eu
|
||||
|
||||
### Phase gate: run only in the intended live-boot phase -----------------------------------------------------------------------
|
||||
PHASE="${1:-}"
|
||||
|
||||
case "${PHASE}" in
|
||||
|
||||
premount)
|
||||
;; ### Continue.
|
||||
*)
|
||||
exit 0 ### Do nothing in other phases.
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
printf "\e[95m[INFO] Starting: [/usr/lib/live/boot/0026-ciss-early-sysctl.sh] ... \n\e[0m"
|
||||
|
||||
echo 2 > /proc/sys/kernel/yama/ptrace_scope 2>/dev/null || true
|
||||
echo 1 > /proc/sys/kernel/unprivileged_bpf_disabled 2>/dev/null || true
|
||||
echo 0 > /proc/sys/fs/suid_dumpable 2>/dev/null || true
|
||||
echo 1 > /proc/sys/kernel/kexec_load_disabled 2>/dev/null || true
|
||||
echo 1 > /proc/sys/fs/protected_symlinks 2>/dev/null || true
|
||||
echo 1 > /proc/sys/fs/protected_hardlinks 2>/dev/null || true
|
||||
echo 2 > /proc/sys/fs/protected_regular 2>/dev/null || true
|
||||
echo 2 > /proc/sys/kernel/kptr_restrict 2>/dev/null || true
|
||||
|
||||
printf "\e[92m[INFO] Successfully applied: [/usr/lib/live/boot/0026-ciss-early-sysctl.sh] \n\e[0m"
|
||||
|
||||
exit 0
|
||||
|
||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||
@@ -4,7 +4,7 @@
|
||||
# shellcheck shell=sh
|
||||
|
||||
# SPDX-Version: 3.0
|
||||
# SPDX-CreationInfo: 2025-10-28; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
# SPDX-CreationInfo: 2025-11-12; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
|
||||
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
@@ -15,11 +15,11 @@
|
||||
# SPDX-Security-Contact: security@coresecret.eu
|
||||
|
||||
### Modified Version of the original file:
|
||||
### https://salsa.debian.org/live-team/live-boot 'components/0030-verify-checksums'
|
||||
### https://salsa.debian.org/live-team/live-boot 'components/0030-ciss-verify-checksums'
|
||||
### In case of successful verification of the offered checksum, proceed with booting; otherwise panic.
|
||||
|
||||
#######################################
|
||||
# Modified checksum-integrity and authenticity-verification-script for continuing the boot process.
|
||||
# Modified checksum-integrity and authenticity-verification-script depending on pinned GPG FPR for boot process verification.
|
||||
# Globals:
|
||||
# LIVE_BOOT_CMDLINE
|
||||
# _TTY
|
||||
@@ -29,9 +29,43 @@
|
||||
# 0 : Successful verification
|
||||
#######################################
|
||||
Verify_checksums() {
|
||||
printf "\e[95m[INFO] CDLB modified: [/usr/lib/live/boot/0030-verify-checksums] ... \n\e[0m"
|
||||
printf "\e[95m[INFO] CDLB modified: [/usr/lib/live/boot/0030-ciss-verify-checksums] ... \n\e[0m"
|
||||
|
||||
### Declare variables --------------------------------------------------------------------------------------------------------
|
||||
|
||||
### Will be replaced at build time:
|
||||
export CDLB_EXP_FPR="@EXP_FPR@"
|
||||
export CDLB_EXP_CA_FPR="@EXP_CA_FPR@"
|
||||
|
||||
### Declare functions --------------------------------------------------------------------------------------------------------
|
||||
|
||||
#######################################
|
||||
# Helper for colored text output on stdout.
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# *: String to print
|
||||
#######################################
|
||||
log_in() { printf '\e[95m[INFO] %s \n\e[0m' "$*"; }
|
||||
|
||||
#######################################
|
||||
# Helper for colored text output on stdout.
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# *: String to print
|
||||
#######################################
|
||||
log_ok() { printf '\e[92m[INFO] %s \n\e[0m' "$*"; }
|
||||
|
||||
#######################################
|
||||
# Helper for colored text output on stdout.
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# *: String to print
|
||||
#######################################
|
||||
log_er() { printf '\e[91m[FATAL] %s \n\e[0m' "$*"; }
|
||||
|
||||
_MOUNTPOINT="${1}"
|
||||
|
||||
_PARAMETER=""
|
||||
@@ -71,19 +105,6 @@ Verify_checksums() {
|
||||
|
||||
done
|
||||
|
||||
### Check GPG pubkey file correct path ---------------------------------------------------------------------------------------
|
||||
for _MP in /lib/live/mount/medium /run/live/medium /cdrom /; do
|
||||
|
||||
if [ -e "${_MP}/0030-verify-checksums.gpg" ]; then
|
||||
|
||||
_KEYFILE="${_MP}/0030-verify-checksums.gpg"
|
||||
|
||||
break
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
### Check if the function should be skipped ----------------------------------------------------------------------------------
|
||||
case "${LIVE_VERIFY_CHECKSUMS}" in
|
||||
|
||||
@@ -97,13 +118,33 @@ Verify_checksums() {
|
||||
|
||||
esac
|
||||
|
||||
### Check GPG pubkey file correct path ---------------------------------------------------------------------------------------
|
||||
for _MP in /lib/live/mount/medium /run/live/medium /cdrom /; do
|
||||
|
||||
if [ -e "${_MP}/${CDLB_EXP_FPR}.gpg" ]; then
|
||||
|
||||
_KEYFILE="${_MP}/${CDLB_EXP_FPR}.gpg"
|
||||
|
||||
if [ -e "${_MP}/${CDLB_EXP_CA_FPR}.gpg" ]; then
|
||||
|
||||
_CA_KEYFILE="${_MP}/${CDLB_EXP_CA_FPR}.gpg"
|
||||
|
||||
fi
|
||||
|
||||
break
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
# shellcheck disable=SC2164
|
||||
cd "${_MOUNTPOINT}"
|
||||
|
||||
|
||||
### CDLB verification of script integrity itself -----------------------------------------------------------------------------
|
||||
if [ "${LIVE_VERIFY_CHECKSUMS_SIGNATURES}" = "true" ]; then
|
||||
|
||||
log_begin_msg "Verifying integrity of: [0030-verify-checksums]"
|
||||
log_begin_msg "Verifying integrity of: [0030-ciss-verify-checksums]"
|
||||
printf "\n"
|
||||
|
||||
_CAND=""
|
||||
@@ -112,7 +153,7 @@ Verify_checksums() {
|
||||
CDLB_CMD="/usr/bin/sha512sum"
|
||||
CDLB_SHA="sha512"
|
||||
|
||||
for _CAND in /scripts/live-bottom/0030-verify-checksums /usr/lib/live/boot/0030-verify-checksums; do
|
||||
for _CAND in /scripts/live-bottom/0030-ciss-verify-checksums /usr/lib/live/boot/0030-ciss-verify-checksums; do
|
||||
|
||||
[ -e "${_CAND}" ] && { CDLB_SCRIPT_SELF="${_CAND}"; break; }
|
||||
|
||||
@@ -124,38 +165,54 @@ Verify_checksums() {
|
||||
CDLB_HASHFILE="${CDLB_SCRIPT_FILE}.${CDLB_SHA}sum.txt"
|
||||
CDLB_SIG_FILE="${CDLB_HASHFILE}.sig"
|
||||
|
||||
_STATUS="$(/usr/bin/gpgv --no-default-keyring --keyring "${_KEYFILE}" --status-fd 1 --verify "${CDLB_SIG_FILE}" "${CDLB_SCRIPT_FULL}" 2>/dev/null)"
|
||||
|
||||
printf "\e[95m[INFO] Verifying integrity of: [%s] ... \n\e[0m" "${CDLB_SCRIPT_FULL}"
|
||||
_CDLB_SIG_FILE_FPR="$(printf '%s\n' "${_STATUS}" | awk '/^\[GNUPG:\] VALIDSIG /{print $3; exit}')"
|
||||
|
||||
printf "\e[95m[INFO] Verifying signature of: [%s] ... \n\e[0m" "${CDLB_SIG_FILE}"
|
||||
### Compare against pinned and expected fingerprint.
|
||||
if [ "${_CDLB_SIG_FILE_FPR}" = "${CDLB_EXP_FPR}" ]; then
|
||||
|
||||
if ! /usr/bin/gpgv --keyring "${_KEYFILE}" --status-fd 1 "${CDLB_SIG_FILE}" "${CDLB_HASHFILE}"; then
|
||||
|
||||
printf "\e[91m[FATAL] Verifying signature of: [%s] failed. \n\e[0m" "${CDLB_SIG_FILE}"
|
||||
sleep 16
|
||||
panic "[FATAL] Verifying signature of: [${CDLB_SIG_FILE}] failed."
|
||||
log_ok "Signature FPR valid: got: [${_CDLB_SIG_FILE_FPR}] expected: [${CDLB_EXP_FPR}]"
|
||||
|
||||
else
|
||||
|
||||
printf "\e[92m[INFO] Verifying signature of: [%s] successful. \n\e[0m" "${CDLB_SIG_FILE}"
|
||||
log_er "Signature FPR mismatch: got: [${_CDLB_SIG_FILE_FPR}] expected: [${CDLB_EXP_FPR}]"
|
||||
sleep 8
|
||||
panic "[FATAL] Signature FPR mismatch: got: [${_CDLB_SIG_FILE_FPR}] expected: [${CDLB_EXP_FPR}]."
|
||||
|
||||
fi
|
||||
|
||||
printf "\e[95m[INFO] Recomputing hash for: [%s] ... \n\e[0m" "${CDLB_SHA}"
|
||||
### Script self-integrity and authenticity checks --------------------------------------------------------------------------
|
||||
### Assumption: initramfs itself is not altered.
|
||||
log_in "Verifying signature of: [${CDLB_SIG_FILE}] ..."
|
||||
|
||||
if ! /usr/bin/gpgv --keyring "${_KEYFILE}" --status-fd 1 "${CDLB_SIG_FILE}" "${CDLB_HASHFILE}"; then
|
||||
|
||||
log_er "Verifying signature of: [${CDLB_SIG_FILE}] failed."
|
||||
sleep 8
|
||||
panic "[FATAL] Verifying signature of: [${CDLB_SIG_FILE}] failed."
|
||||
|
||||
else
|
||||
|
||||
log_ok "Verifying signature of: [${CDLB_SIG_FILE}] successful."
|
||||
|
||||
fi
|
||||
|
||||
log_in "Recomputing hash for: [${CDLB_SHA}] ..."
|
||||
|
||||
CDLB_COMPUTED=$("${CDLB_CMD}" "${CDLB_SCRIPT_FULL}" | { read -r first _ || exit 1; printf '%s\n' "${first}"; })
|
||||
IFS=' ' read -r CDLB_EXPECTED _ < "${CDLB_HASHFILE}"
|
||||
|
||||
if [ "${CDLB_COMPUTED}" != "${CDLB_EXPECTED}" ]; then
|
||||
|
||||
printf "\e[91m[FATAL] Recomputing hash for: [%s] failed. \n\e[0m" "${CDLB_SHA}"
|
||||
sleep 16
|
||||
panic "[FATAL] Recomputing hash for: [${CDLB_SHA}] failed."
|
||||
log_er "Recomputing hash for: [${CDLB_SHA}] failed."
|
||||
sleep 8
|
||||
panic "[FATAL] Recomputing hash for: [${CDLB_SHA}] failed."
|
||||
|
||||
fi
|
||||
|
||||
printf "\e[92m[INFO] Recomputing hash for: [%s] successful. \n\e[0m" "${CDLB_SHA}"
|
||||
printf "\e[92m[INFO] Verification of authenticity and integrity of [%s] successfully completed. \n\e[0m" "${CDLB_SCRIPT_FULL}"
|
||||
log_ok "Recomputing hash for: [${CDLB_SHA}] successful."
|
||||
log_ok "Verification of authenticity and integrity of [${CDLB_SCRIPT_FULL}] successfully completed."
|
||||
log_end_msg
|
||||
printf "\n"
|
||||
|
||||
@@ -164,7 +221,7 @@ Verify_checksums() {
|
||||
### Checksum and checksum signature verification -----------------------------------------------------------------------------
|
||||
log_begin_msg "Verifying checksums"
|
||||
printf "\n"
|
||||
printf "\e[95m[INFO] Verifying checksums ... \n\e[0m"
|
||||
log_in "Verifying checksums ..."
|
||||
|
||||
# shellcheck disable=SC2001
|
||||
for _DIGEST in $(echo "${LIVE_VERIFY_CHECKSUMS_DIGESTS}" | sed -e 's|,| |g'); do
|
||||
@@ -176,27 +233,27 @@ Verify_checksums() {
|
||||
|
||||
if [ -e "${_CHECKSUM}" ]; then
|
||||
|
||||
printf "\e[95m[INFO] Found: [%s] ... \n\e[0m" "${_CHECKSUM}"
|
||||
log_in "Found: [${_CHECKSUM}] ..."
|
||||
|
||||
if [ -e "/usr/bin/${_DIGEST}sum" ]; then
|
||||
|
||||
printf "\e[95m[INFO] Found: [%s] ... \n\e[0m" "/usr/bin/${_DIGEST}sum"
|
||||
log_in "Found: [/usr/bin/${_DIGEST}sum] ..."
|
||||
|
||||
if [ "${LIVE_VERIFY_CHECKSUMS_SIGNATURES}" = "true" ]; then
|
||||
|
||||
printf "\e[95m[INFO] Checking signature of: [%s] ... \n\e[0m" "${_CHECKSUM}"
|
||||
log_in "Checking signature of: [${_CHECKSUM}] ..."
|
||||
|
||||
_CHECKSUM_SIGNATURE="${_CHECKSUM}.sig"
|
||||
|
||||
if /usr/bin/gpgv --keyring "${_KEYFILE}" --status-fd 1 "${_CHECKSUM_SIGNATURE}" "${_CHECKSUM}"; then
|
||||
|
||||
_RETURN_PGP="${?}"
|
||||
printf "\e[92m[INFO] Checking signature of: [%s] successful. \n\e[0m" "${_CHECKSUM}"
|
||||
log_in "Checking signature of: [${_CHECKSUM}] successful."
|
||||
|
||||
else
|
||||
|
||||
_RETURN_PGP="${?}"
|
||||
printf "\e[91m[FATAL] Checking signature of: [%s] failed. \n\e[0m" "${_CHECKSUM}"
|
||||
log_er "Checking signature of: [${_CHECKSUM}] failed."
|
||||
|
||||
fi
|
||||
|
||||
@@ -210,12 +267,12 @@ Verify_checksums() {
|
||||
if grep -v '^#' "${_CHECKSUM}" | /usr/bin/"${_DIGEST}"sum -c > "${_TTY}"; then
|
||||
|
||||
_RETURN_SHA="${?}"
|
||||
printf "\e[92m[INFO] Found: [%s] successful verified: [%s] \n\e[0m" "/usr/bin/${_DIGEST}sum" "${_CHECKSUM}"
|
||||
log_ok "Found: [/usr/bin/${_DIGEST}sum] successful verified: [${_CHECKSUM}]"
|
||||
|
||||
else
|
||||
|
||||
_RETURN_SHA="${?}"
|
||||
printf "\e[91m[FATAL] Found: [%s] unsuccessful verified: [%s] \n\e[0m" "/usr/bin/${_DIGEST}sum" "${_CHECKSUM}"
|
||||
log_er "Found: [/usr/bin/${_DIGEST}sum] unsuccessful verified: [${_CHECKSUM}]"
|
||||
|
||||
fi
|
||||
|
||||
@@ -225,7 +282,7 @@ Verify_checksums() {
|
||||
else
|
||||
|
||||
_RETURN_SHA="255"
|
||||
printf "\e[93m[WARN] NOT Found [%s]. \n\e[0m" "/usr/bin/${_DIGEST}sum"
|
||||
log_er "NOT Found [/usr/bin/${_DIGEST}sum]."
|
||||
|
||||
fi
|
||||
|
||||
@@ -241,40 +298,35 @@ Verify_checksums() {
|
||||
case "${_RETURN_PGP},${_RETURN_SHA}" in
|
||||
|
||||
"0,0")
|
||||
printf "\e[92m[INFO] Verification of [GPG signature] and [sha checksum] file successful; continuing booting in 8 seconds. \n\e[0m"
|
||||
printf "\e[92m[INFO] CDLB modified: [%s] done. \n\e[0m" "${CDLB_SCRIPT_FULL}"
|
||||
sleep 8
|
||||
log_ok "Verification of [GPG signature] and [sha checksum] file successful; continuing booting in 8 seconds."
|
||||
log_success_msg "Verification of [GPG signature] and [sha checksum] file successful; continuing booting in 8 seconds."
|
||||
sleep 8
|
||||
return 0
|
||||
;;
|
||||
|
||||
"na,0")
|
||||
printf "\e[92m[INFO] Verification of [sha checksum] file successful; continuing booting in 8 seconds. \n\e[0m"
|
||||
printf "\e[92m[INFO] CDLB modified: [%s] done. \n\e[0m" "${CDLB_SCRIPT_FULL}"
|
||||
sleep 8
|
||||
log_ok "Verification of [sha checksum] file successful; continuing booting in 8 seconds."
|
||||
log_success_msg "Verification of [sha checksum] file successful; continuing booting in 8 seconds."
|
||||
sleep 8
|
||||
return 0
|
||||
;;
|
||||
|
||||
"0,"*)
|
||||
printf "\e[91m[FATAL] Verification of [GPG signature] file successful, while verification of [sha checksum] file failed. \n\e[0m"
|
||||
printf "\e[91m[FATAL] CDLB modified: [%s] done. \n\e[0m" "${CDLB_SCRIPT_FULL}"
|
||||
log_er "Verification of [GPG signature] file successful, while verification of [sha checksum] file failed."
|
||||
sleep 8
|
||||
panic "Verification of [GPG signature] file successful, while verification of [sha checksum] file failed."
|
||||
panic "Verification of [GPG signature] file successful, while verification of [sha checksum] file failed."
|
||||
;;
|
||||
|
||||
*",0")
|
||||
printf "\e[91m[FATAL] Verification of [GPG signature] file failed, while verification of [sha checksum] file successful. \n\e[0m"
|
||||
printf "\e[91m[FATAL] CDLB modified: [%s] done. \n\e[0m" "${CDLB_SCRIPT_FULL}"
|
||||
log_er "Verification of [GPG signature] file failed, while verification of [sha checksum] file successful."
|
||||
sleep 8
|
||||
panic "Verification of [GPG signature] file failed, while verification of [sha checksum] file successful."
|
||||
panic "Verification of [GPG signature] file failed, while verification of [sha checksum] file successful."
|
||||
;;
|
||||
|
||||
"na,"*)
|
||||
printf "\e[91m[FATAL] Verification of [sha checksum] file failed. \n\e[0m"
|
||||
printf "\e[91m[FATAL] CDLB modified: [%s] done. \n\e[0m" "${CDLB_SCRIPT_FULL}"
|
||||
log_er "Verification of [sha checksum] file failed."
|
||||
sleep 8
|
||||
panic "Verification of checksum file failed."
|
||||
panic "Verification of [sha checksum] file failed."
|
||||
;;
|
||||
|
||||
esac
|
||||
@@ -0,0 +1,194 @@
|
||||
#!/bin/sh
|
||||
# bashsupport disable=BP5007
|
||||
# shellcheck disable=SC2249
|
||||
# shellcheck shell=sh
|
||||
|
||||
# SPDX-Version: 3.0
|
||||
# SPDX-CreationInfo: 2025-11-12; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
|
||||
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||
# SPDX-FileType: SOURCE
|
||||
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
|
||||
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
|
||||
# SPDX-PackageName: CISS.debian.live.builder
|
||||
# SPDX-Security-Contact: security@coresecret.eu
|
||||
|
||||
# Purpose: Late rootfs attestation and dmsetup health checking.
|
||||
# Phase : bottom (executed by live-boot inside the initramfs).
|
||||
|
||||
set -eu
|
||||
|
||||
### Phase gate: run only in the intended live-boot phase -----------------------------------------------------------------------
|
||||
PHASE="${1:-}"
|
||||
|
||||
case "${PHASE}" in
|
||||
|
||||
bottom)
|
||||
;; ### Continue.
|
||||
*)
|
||||
exit 0 ### Do nothing in other phases.
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
printf "\e[95m[INFO] Starting: [/usr/lib/live/boot/0042-ciss-post-decrypt-attest] ... \n\e[0m"
|
||||
|
||||
### Declare variables ----------------------------------------------------------------------------------------------------------
|
||||
|
||||
### Will be replaced at build time:
|
||||
export CDLB_EXP_FPR="@EXP_FPR@"
|
||||
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 ----------------------
|
||||
CDLB_MAPPER_NAME="${CDLB_MAPPER_NAME:-ciss_rootfs.crypt}"
|
||||
|
||||
### Attestation file locations inside decrypted rootfs. ------------------------------------------------------------------------
|
||||
CDLB_ATTEST_FPR_SHA="${CDLB_ATTEST_FPR_SHA:-/.ciss/attest/${CDLB_EXP_FPR}.sha512sum.txt}"
|
||||
CDLB_ATTEST_FPR_SIG="${CDLB_ATTEST_FPR_SIG:-/.ciss/attest/${CDLB_EXP_FPR}.sha512sum.txt.sig}"
|
||||
CDLB_KEY_DIR="${CDLB_KEY_DIR:-/etc/ciss/keys}"
|
||||
|
||||
### Declare functions ----------------------------------------------------------------------------------------------------------
|
||||
|
||||
#######################################
|
||||
# Helper for colored text output on stdout.
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# *: String to print
|
||||
#######################################
|
||||
log_in() { printf '\e[95m[INFO] %s \n\e[0m' "$*"; }
|
||||
|
||||
#######################################
|
||||
# Helper for colored text output on stdout.
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# *: String to print
|
||||
#######################################
|
||||
log_ok() { printf '\e[92m[INFO] %s \n\e[0m' "$*"; }
|
||||
|
||||
#######################################
|
||||
# Helper for colored text output on stdout.
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# *: String to print
|
||||
#######################################
|
||||
log_er() { printf '\e[91m[FATAL] %s \n\e[0m' "$*"; }
|
||||
|
||||
### Locate decrypted rootfs mount ----------------------------------------------------------------------------------------------
|
||||
_mp=""
|
||||
ROOTMP=""
|
||||
|
||||
for _mp in /run/live/rootfs /run/live/rootfs.squashfs /run/live/overlay /root ; do
|
||||
|
||||
if [ -d "${_mp}" ] && [ -e "${_mp}/etc" ]; then ROOTMP="${_mp}"; break; fi
|
||||
|
||||
done
|
||||
|
||||
if [ -z "${ROOTMP}" ]; then
|
||||
log_er "No decrypted rootfs mount found."
|
||||
sleep 8
|
||||
# TODO: Remove debug mode
|
||||
# panic "[FATAL] No decrypted rootfs mount found."
|
||||
fi
|
||||
|
||||
log_ok "Decrypted rootfs at: [${ROOTMP}]"
|
||||
|
||||
HASH_FILE="${ROOTMP}${CDLB_ATTEST_FPR_SHA}"
|
||||
SIGN_FILE="${ROOTMP}${CDLB_ATTEST_FPR_SIG}"
|
||||
KEYFILE="${ROOTMP}${CDLB_KEY_DIR}/${CDLB_EXP_FPR}.gpg"
|
||||
|
||||
[ -n "${KEYFILE}" ] || { log_er "No public key found under: [${ROOTMP}${CDLB_KEY_DIR}/${CDLB_EXP_FPR}.gpg]"; exit 42; }
|
||||
[ -s "${HASH_FILE}" ] || { log_er "Attestation data missing: [${HASH_FILE}]"; exit 42; }
|
||||
[ -s "${SIGN_FILE}" ] || { log_er "Attestation signature missing: [${SIGN_FILE}]"; exit 42; }
|
||||
|
||||
log_in "Verifying rootfs attestation with 'gpgv' and inside LUKS encrypted rootfs pinned GPG FPR."
|
||||
_STATUS="$(${GPGV} --no-default-keyring --keyring "${KEYFILE}" --status-fd 1 --verify "${SIGN_FILE}" "${HASH_FILE}" 2>/dev/null)"
|
||||
_CDLB_SIG_FILE_FPR="$(printf '%s\n' "${_STATUS}" | awk '/^\[GNUPG:\] VALIDSIG /{print $3; exit}')"
|
||||
|
||||
### Compare against pinned and expected fingerprint. ---------------------------------------------------------------------------
|
||||
if [ "${_CDLB_SIG_FILE_FPR}" = "${CDLB_EXP_FPR}" ]; then
|
||||
|
||||
log_ok "Signature FPR valid: got: [${_CDLB_SIG_FILE_FPR}] expected: [${CDLB_EXP_FPR}]"
|
||||
|
||||
else
|
||||
|
||||
log_er "Signature FPR mismatch: got: [${_CDLB_SIG_FILE_FPR}] expected: [${CDLB_EXP_FPR}]"
|
||||
sleep 8
|
||||
# TODO: Remove debug mode
|
||||
# panic "[FATAL] Signature FPR mismatch: got: [${_CDLB_SIG_FILE_FPR}] expected: [${CDLB_EXP_FPR}]."
|
||||
|
||||
fi
|
||||
|
||||
### 'dmsetup' health check -----------------------------------------------------------------------------------------------------
|
||||
MAP_DEV="/dev/mapper/${CDLB_MAPPER_NAME}"
|
||||
if [ -e "${MAP_DEV}" ]; then
|
||||
|
||||
log_in "Checking dmsetup table for ${MAP_DEV}"
|
||||
|
||||
TOP_LINE="$(/usr/sbin/dmsetup table --showkeys "${MAP_DEV}" 2>/dev/null | awk 'NR==1{print; exit}')"
|
||||
if printf '%s\n' "${TOP_LINE}" | grep -q ' crypt '; then
|
||||
|
||||
log_ok "Top layer is 'crypt'."
|
||||
|
||||
else
|
||||
|
||||
log_er "Top layer is NOT 'crypt'."
|
||||
sleep 8
|
||||
# TODO: Remove debug mode
|
||||
# panic "[FATAL] Top layer is NOT 'crypt'."
|
||||
|
||||
fi
|
||||
|
||||
if printf '%s\n' "${TOP_LINE}" | grep -Eq ' xts|aes-xts'; then
|
||||
|
||||
log_ok "Cipher looks like AES-XTS."
|
||||
|
||||
else
|
||||
|
||||
log_er "Cipher does not look like AES-XTS."
|
||||
sleep 8
|
||||
# TODO: Remove debug mode
|
||||
# panic "[FATAL] Cipher does not look like AES-XTS."
|
||||
|
||||
fi
|
||||
|
||||
### Extract child device token (the second last field is 'device', the last is 'offset.') --------------------------------------
|
||||
CHILD_TOK="$(printf '%s\n' "${TOP_LINE}" | awk '{print $(NF-1)}')"
|
||||
CHILD_NAME="${CHILD_TOK}"
|
||||
|
||||
case "${CHILD_TOK}" in
|
||||
|
||||
*:* )
|
||||
if [ -e "/sys/dev/block/${CHILD_TOK}/dm/name" ]; then
|
||||
CHILD_NAME="$(cat "/sys/dev/block/${CHILD_TOK}/dm/name" 2>/dev/null || true)"
|
||||
[ -n "${CHILD_NAME}" ] || CHILD_NAME="${CHILD_TOK}"
|
||||
fi
|
||||
;;
|
||||
|
||||
/dev/* )
|
||||
CHILD_NAME="$(basename -- "${CHILD_TOK}")"
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
#### Child layer must be 'integrity' with hmac and sha512 and 4096-byte sectors (best-effort greps). ---------------------------
|
||||
log_in "Checking underlying integrity target: ${CHILD_NAME}"
|
||||
|
||||
CHILD_TAB="$(/usr/sbin/dmsetup table --showkeys "${CHILD_NAME}" 2>/dev/null || true)"
|
||||
printf '%s\n' "${CHILD_TAB}" | grep -q ' integrity ' || { log_er "Underlying layer is not 'integrity'"; }
|
||||
printf '%s\n' "${CHILD_TAB}" | grep -qi 'hmac' || { log_er "Integrity target not using keyed MAC (hmac)"; }
|
||||
printf '%s\n' "${CHILD_TAB}" | grep -qi 'sha512' || { log_er "Integrity algo not sha512"; }
|
||||
printf '%s\n' "${CHILD_TAB}" | grep -Eq '\b4096\b' || { log_er "Expected 4096-byte sector size not found"; }
|
||||
|
||||
log_ok "dm-crypt and dm-integrity(HMAC-SHA512, 4096B) chain looks healthy."
|
||||
|
||||
fi
|
||||
|
||||
printf "\e[92m[INFO] Successfully applied: [/usr/lib/live/boot/0042-ciss-post-decrypt-attest]\n\e[0m"
|
||||
|
||||
exit 0
|
||||
|
||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||
Reference in New Issue
Block a user