mirror of
https://codeberg.org/andersonarc/reliant-system.git
synced 2025-11-13 12:50:38 -05:00
more fixes, add argon2 patch
This commit is contained in:
parent
c28c503296
commit
0830eb4e45
11 changed files with 150 additions and 86 deletions
2
build.sh
Normal file → Executable file
2
build.sh
Normal file → Executable file
|
|
@ -2,5 +2,7 @@
|
|||
set -euo pipefail
|
||||
|
||||
# Build Shufflecake
|
||||
echo "[INFO]: Building qubes-sflc..."
|
||||
cd qubes-sflc
|
||||
./build.sh
|
||||
echo "[INFO]: Build complete."
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ depends() {
|
|||
|
||||
install() {
|
||||
# Interactive script
|
||||
inst_simple "$moddir/scripts/reliant-initramfs.sh" "/usr/local/share/scripts/reliant-initramfs.sh"
|
||||
inst_script "$moddir/scripts/reliant-initramfs.sh" "/usr/local/share/scripts/reliant-initramfs.sh"
|
||||
|
||||
# Main service
|
||||
inst_simple "$moddir/reliant.service" "/etc/systemd/system/reliant.service"
|
||||
inst "$moddir/reliant.service" "/etc/systemd/system/reliant.service"
|
||||
systemctl --root="$initdir" enable reliant.service
|
||||
|
||||
# Shufflecake
|
||||
|
|
@ -28,10 +28,12 @@ install() {
|
|||
# TODO: Do we need udev rules to --setro newly attached devices?
|
||||
|
||||
# Reliant
|
||||
for file in "/usr/local/share/scripts/reliant-*" "/usr/local/sbin/reliant-*" "/usr/local/bin/surgeon-*"; do
|
||||
inst_binary "$file"
|
||||
done
|
||||
inst_simple "/etc/reliant.conf"
|
||||
inst_script /usr/local/share/scripts/reliant-common.sh
|
||||
inst_script /usr/local/sbin/reliant-security
|
||||
inst_script /usr/local/sbin/surgeon-suture
|
||||
inst_script /usr/local/sbin/reliant-mount
|
||||
inst_script /usr/local/sbin/reliant-hash
|
||||
inst /etc/reliant.conf
|
||||
|
||||
# Other binaries
|
||||
inst_multiple dmesg lsblk blockdev mount dd wc sed sleep md5sum find modprobe cut grep mkdir rm tail
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export RELIANT_INITRAMFS=$RELIANT_TRUE
|
|||
# Upon encountering issues, prompt the user for the next course of action
|
||||
reliant_prompt_user() {
|
||||
while true; do
|
||||
REPLY=$(plymouth ask-question --prompt="System might be compromised. Proceed? [Y(es)/N(o)/S(kip)]: ")
|
||||
REPLY=$(plymouth ask-question --prompt="System might be compromised. Proceed? [Y(es)/N(o)/S(kip)]")
|
||||
case $REPLY in
|
||||
[Yy]*)
|
||||
# User confirmed the system is safe to boot
|
||||
|
|
@ -29,16 +29,16 @@ reliant_prompt_user() {
|
|||
exit 0 ;;
|
||||
|
||||
*)
|
||||
plymouth display-message --text="Invalid response. [Y(es)/N(o)/S(kip)]: "
|
||||
plymouth display-message --text="Invalid response."
|
||||
sleep 1
|
||||
plymouth hide-message --text="Invalid response. [Y(es)/N(o)/S(kip)]: "
|
||||
plymouth hide-message --text="Invalid response."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Ensures the canary files have been wiped by previous shutdown
|
||||
reliant_initramfs_check_canaries() {
|
||||
reliant_security_initramfs_check_canaries() {
|
||||
# /rootfs.canary
|
||||
if [ -f /rootfs.canary ]; then
|
||||
reliant_error "reliant_initramfs_check_canaries: /rootfs.canary exists!"
|
||||
|
|
@ -73,14 +73,25 @@ reliant_initramfs_check_canaries() {
|
|||
|
||||
# Verifies that the initramfs cannot leak information via non-volatile media, logs or network
|
||||
reliant_security_check_initramfs() {
|
||||
# Run the common checks
|
||||
reliant-security /sysroot || return $RELIANT_SECURITY_FAIL
|
||||
|
||||
# Run the common checks first
|
||||
status_common=$RELIANT_OK
|
||||
reliant-security /sysroot || status_common=$?
|
||||
# No need to report, already done
|
||||
|
||||
# Check canaries
|
||||
reliant_security_initramfs_check_canaries || return $RELIANT_SECURITY_FAIL
|
||||
|
||||
# Pass
|
||||
return 0
|
||||
status_canaries=$RELIANT_OK
|
||||
reliant_security_initramfs_check_canaries || status_canaries=$?
|
||||
echo "[CANARIES]: $(reliant_err2str $status_canaries)"
|
||||
|
||||
# Calculate and return the verdict
|
||||
echo -n "[VERDICT]: "
|
||||
if [ $status_common -eq $RELIANT_OK ] && [ $status_canaries -eq $RELIANT_OK ]; then
|
||||
echo "SAFE TO BOOT"
|
||||
return $RELIANT_OK
|
||||
else
|
||||
echo "POTENTIALLY COMPROMISED"
|
||||
return $RELIANT_SECURITY_FAIL
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function
|
||||
|
|
|
|||
13
install.sh
13
install.sh
|
|
@ -22,6 +22,7 @@ fi
|
|||
: "${RELIANT_SKIP_CHECKSUM:=}"
|
||||
: "${RELIANT_SPARSE_SAMPLES:=512}"
|
||||
: "${RELIANT_BOOTSTRAP_QUBE:=bootstrap}"
|
||||
: "${RELIANT_KERNEL_VERSION:=$(qvm-run --pass-io "$RELIANT_BOOTSTRAP_QUBE" 'uname -r')}"
|
||||
|
||||
# Validate configuration values
|
||||
if [ -z "$RELIANT_SECURE_DEVICE" ]; then
|
||||
|
|
@ -86,6 +87,10 @@ reliant_install_dracut() {
|
|||
reliant_install_file "$1" "$RELIANT_DRACUT_DIR/$2" "$3" "$4" "$5"
|
||||
}
|
||||
|
||||
# Run the build script inside of the bootstrap qube
|
||||
echo "[INFO]: Building $RELIANT_BOOTSTRAP_QUBE:$RELIANT_SYSTEM_ROOT for kernel $RELIANT_KERNEL_VERSION..."
|
||||
qvm-run --pass-io "$RELIANT_BOOTSTRAP_QUBE" "sh -c 'cd $RELIANT_SYSTEM_ROOT && ./build.sh'"
|
||||
|
||||
# Begin the installation process
|
||||
echo "[INFO]: Installing reliant-system from $RELIANT_BOOTSTRAP_QUBE:$RELIANT_SYSTEM_ROOT..."
|
||||
|
||||
|
|
@ -118,7 +123,7 @@ reliant_install_dracut dracut/99reliant/scripts/reliant-initramfs.sh scripts/rel
|
|||
reliant_install_dracut dracut/99reliant/patches/create-snapshot.sh patches/create-snapshot.sh 0755 root root
|
||||
|
||||
# reliant-system/qubes-sflc
|
||||
reliant_install_file qubes-sflc/dm-sflc.ko "/usr/lib/modules/$(uname -r)/extra" 0644 root root
|
||||
reliant_install_file qubes-sflc/dm-sflc.ko "/usr/lib/modules/$RELIANT_KERNEL_VERSION/extra/dm-sflc.ko" 0644 root root
|
||||
reliant_install_sbin qubes-sflc/shufflecake shufflecake 0744 root root
|
||||
|
||||
echo "[INFO]: Successfully copied files to dom0."
|
||||
|
|
@ -158,11 +163,11 @@ systemctl enable shufflecake-close.service
|
|||
surgeon-dissect -t varlibqubes
|
||||
reliant-snapshot-rw
|
||||
|
||||
# reliant-system/qubes-sflc
|
||||
depmod -a "$RELIANT_KERNEL_VERSION"
|
||||
|
||||
# reliant-system/dracut
|
||||
dracut --force --regenerate-all
|
||||
|
||||
# reliant-system/qubes-sflc
|
||||
depmod
|
||||
|
||||
# Report successful installation
|
||||
echo "[INFO]: Installation complete. Reboot to enter protected mode."
|
||||
|
|
|
|||
|
|
@ -2,9 +2,29 @@
|
|||
set -euo pipefail
|
||||
|
||||
# Download the submodules
|
||||
git submodule init --update --recursive
|
||||
echo "[INFO]: Updating git submodules..."
|
||||
git submodule update --init --recursive
|
||||
|
||||
# Apply the Argon2 memory parameter patch
|
||||
echo "[INFO]: Applying Argon2 memory patch to improve KDF resilience..."
|
||||
|
||||
# Change the working directory
|
||||
OLD_PWD=$PWD
|
||||
cd shufflecake-c
|
||||
|
||||
# Apply the patch
|
||||
CRYPTO_H=shufflecake-userland/include/utils/crypto.h
|
||||
git restore $CRYPTO_H
|
||||
patch $CRYPTO_H "$OLD_PWD/crypto.h.patch"
|
||||
|
||||
# Return back to qubes-sflc
|
||||
cd "$OLD_PWD"
|
||||
|
||||
# Notify user of a breaking change
|
||||
echo "[WARN]: Your new Argon2 memory parameter is 2097152 KiB, INCOMPATIBLE with default Shufflecake."
|
||||
|
||||
# Ensure Docker is running
|
||||
echo "[INFO]: Starting the Docker container..."
|
||||
sudo systemctl start docker
|
||||
|
||||
# Build and execute the container
|
||||
|
|
@ -12,5 +32,9 @@ sudo docker build -t qubes-sflc .
|
|||
sudo docker run --rm -v /usr/lib/modules:/usr/lib/modules:ro -v $PWD/shufflecake-c:/root/shufflecake-c qubes-sflc
|
||||
|
||||
# Copy artifacts
|
||||
cp shufflecake-c/dm-sflc.ko $PWD/dm-sflc.ko
|
||||
cp shufflecake-c/shufflecake $PWD/shufflecake
|
||||
echo "[INFO]: Copying build artifacts..."
|
||||
cp shufflecake-c/dm-sflc.ko "$PWD/dm-sflc.ko"
|
||||
cp shufflecake-c/shufflecake "$PWD/shufflecake"
|
||||
|
||||
# Restore the original crypto.h to avoid interference with future updates
|
||||
git restore "shufflecake-c/$CRYPTO_H"
|
||||
|
|
|
|||
13
qubes-sflc/crypto.h.patch
Normal file
13
qubes-sflc/crypto.h.patch
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
diff --git a/shufflecake-userland/include/utils/crypto.h b/shufflecake-userland/include/utils/crypto.h
|
||||
index 8366134..303b2ae 100644
|
||||
--- a/shufflecake-userland/include/utils/crypto.h
|
||||
+++ b/shufflecake-userland/include/utils/crypto.h
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
// Argon memory parameter
|
||||
// We assume machines with at least 128 MiB available RAM, so 2^17 kiB
|
||||
-#define SFLC_ARGON_M (1 << 17) /* kibibytes */
|
||||
+#define SFLC_ARGON_M 2097152 /* kibibytes */
|
||||
|
||||
// Argon iterations count
|
||||
// We aim for 1-2 seconds on a low-end laptop or mobile (it's a one-time operation)
|
||||
|
|
@ -23,8 +23,9 @@ modprobe dm-sflc
|
|||
|
||||
# Prompt the user for their password
|
||||
while true; do
|
||||
if plymouth ask-for-password --prompt="Auxillary password" | shufflecake open "$SECURE_DEVICE" &>/dev/null; then
|
||||
if plymouth ask-for-password --prompt="Auxillary password" | shufflecake open "$RELIANT_SECURE_DEVICE" &>/dev/null; then
|
||||
plymouth display-message --text="Success"
|
||||
break
|
||||
else
|
||||
plymouth display-message --text="Invalid password"
|
||||
sleep 2
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ fi
|
|||
name=$1
|
||||
|
||||
echo -n "Destroying links... "
|
||||
for appvm in /run/shufflecake/$name/appvms/*; do
|
||||
for appvm in "/run/shufflecake/$name/appvms/"*; do
|
||||
qube="${appvm##*/}"
|
||||
|
||||
# Shutdown
|
||||
|
|
@ -31,8 +31,8 @@ for appvm in /run/shufflecake/$name/appvms/*; do
|
|||
|
||||
# Remove directory
|
||||
directory="/var/lib/qubes/appvms/$qube"
|
||||
if [ -d $directory ]; then
|
||||
rm -rf $directory
|
||||
if [ -d "$directory" ]; then
|
||||
rm -rf "$directory"
|
||||
fi
|
||||
done
|
||||
echo "Done."
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ fi
|
|||
# No more variable checks needed
|
||||
set -u
|
||||
|
||||
# Require superuser permissions
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
reliant_fail "must be superuser"
|
||||
fi
|
||||
|
||||
# Kernel command line check
|
||||
reliant_security_check_cmdline() {
|
||||
# Check if /proc/cmdline exists
|
||||
|
|
@ -94,7 +99,7 @@ reliant_security_check_network() {
|
|||
# Persistent, real filesystems must be readonly
|
||||
reliant_security_check_filesystems() {
|
||||
# Check each mountpoint
|
||||
mount | while IFS= read -r line; do
|
||||
mount | while read -r line; do
|
||||
# Determine the filesystem type
|
||||
filesystem_type=$(echo "$line" | awk '{ print $5 }' )
|
||||
|
||||
|
|
@ -115,7 +120,7 @@ reliant_security_check_filesystems() {
|
|||
esac
|
||||
done
|
||||
|
||||
# Pass from subshell
|
||||
# Pass status from subshell
|
||||
return $?
|
||||
}
|
||||
|
||||
|
|
@ -139,68 +144,64 @@ reliant_security_check_overlay() {
|
|||
fi
|
||||
|
||||
# Find the mountpoint
|
||||
mount | while IFS= read -r line; do
|
||||
# Determine the mountpoint
|
||||
filesystem_mountpoint=$(echo "$line" | awk '{ print $3 }')
|
||||
mount | {
|
||||
found=$RELIANT_FALSE
|
||||
while read -r line; do
|
||||
# Filter by mountpoint
|
||||
filesystem_mountpoint=$(echo "$line" | awk '{ print $3 }')
|
||||
if [ "$filesystem_mountpoint" != "$1" ]; then continue; fi
|
||||
|
||||
# Skip if not matching
|
||||
if [ "$filesystem_mountpoint" != "$1" ]; then continue; fi
|
||||
|
||||
# Determine the filesystem flags
|
||||
filesystem_flags=$(echo "$line" | awk '{ print $6 }')
|
||||
|
||||
# Iterate the flags
|
||||
upper_found=$RELIANT_FALSE
|
||||
work_found=$RELIANT_FALSE
|
||||
IFS=','
|
||||
for flag in $filesystem_flags; do
|
||||
case $flag in
|
||||
'upperdir=/run/systemd/overlay-sysroot/upper') upper_found=0 ;;
|
||||
'workdir=/run/systemd/overlay-sysroot/work' ) work_found=0 ;;
|
||||
esac
|
||||
# Filter by filesystem type
|
||||
filesystem_type=$(echo "$line" | awk '{ print $5 }' )
|
||||
if [ "$filesystem_type" != "overlay" ]; then continue; fi
|
||||
|
||||
# Determine the filesystem flags
|
||||
filesystem_flags=$(echo "$line" | awk '{ print $6 }')
|
||||
|
||||
# Iterate the flags
|
||||
upper_found=$RELIANT_FALSE
|
||||
work_found=$RELIANT_FALSE
|
||||
IFS=','
|
||||
for flag in $filesystem_flags; do
|
||||
case $flag in
|
||||
'upperdir=/run/systemd/overlay-sysroot/upper') upper_found=$RELIANT_TRUE ;;
|
||||
'workdir=/run/systemd/overlay-sysroot/work' ) work_found=$RELIANT_TRUE ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check if they have been validated
|
||||
if [ $work_found -ne $RELIANT_TRUE ]; then
|
||||
reliant_error "reliant_security_check_overlay: workdir for $1 could not be validated"
|
||||
exit $RELIANT_SECURITY_FAIL
|
||||
fi
|
||||
if [ $upper_found -ne $RELIANT_TRUE ]; then
|
||||
reliant_error "reliant_security_check_overlay: upperdir for $1 could not be validated"
|
||||
exit $RELIANT_SECURITY_FAIL
|
||||
fi
|
||||
|
||||
# Indicate that the mountpoint has been found
|
||||
found=$RELIANT_TRUE
|
||||
break
|
||||
done
|
||||
|
||||
# Check if they have been validated
|
||||
if [ $work_found -ne $RELIANT_TRUE ]; then
|
||||
reliant_error "reliant_security_check_overlay: workdir for $1 could not be validated"
|
||||
exit $RELIANT_SECURITY_FAIL
|
||||
fi
|
||||
if [ $upper_found -ne $RELIANT_TRUE ]; then
|
||||
reliant_error "reliant_security_check_overlay: upperdir for $1 could not be validated"
|
||||
# Check if the mountpoint has been found within the loop
|
||||
if [ $found -ne $RELIANT_TRUE ]; then
|
||||
reliant_error "reliant_security_check_overlay: mountpoint for overlay root on $1 not found"
|
||||
exit $RELIANT_SECURITY_FAIL
|
||||
else
|
||||
exit $RELIANT_OK
|
||||
fi
|
||||
}
|
||||
|
||||
# Indicate that the mountpoint has been found
|
||||
exit 255
|
||||
done
|
||||
status=$?
|
||||
|
||||
# Check the subshell return code
|
||||
case "$status" in
|
||||
0)
|
||||
# Not found
|
||||
reliant_error "reliant_security_check_overlay: mountpoint $1 not found"
|
||||
return $RELIANT_FAIL
|
||||
;;
|
||||
|
||||
255)
|
||||
# Found
|
||||
return $RELIANT_OK
|
||||
;;
|
||||
|
||||
*)
|
||||
# Other issues
|
||||
reliant_error "reliant_security_check_overlay: mountpoint $1 verification failed"
|
||||
return $status
|
||||
;;
|
||||
esac
|
||||
# Forward from subshell
|
||||
return $?
|
||||
}
|
||||
|
||||
# Checksum verification
|
||||
reliant_security_check_devices() {
|
||||
IFS=$'\n'
|
||||
for device in $(lsblk -rno name); do
|
||||
device_path="/dev/$device"
|
||||
for device_path in $(lsblk -rnpo name); do
|
||||
device="${device_path##*/}"
|
||||
|
||||
# Check if it is a valid block device
|
||||
if [ ! -b "$device_path" ]; then return $RELIANT_BUG; fi
|
||||
|
|
@ -214,6 +215,7 @@ reliant_security_check_devices() {
|
|||
|
||||
# User-specified devices will be excluded
|
||||
should_skip=$RELIANT_FALSE
|
||||
IFS=' '
|
||||
for skip_device in $RELIANT_SKIP_CHECKSUM; do
|
||||
if [ "$skip_device" = "$device_path" ]; then
|
||||
should_skip=$RELIANT_TRUE
|
||||
|
|
@ -232,7 +234,7 @@ reliant_security_check_devices() {
|
|||
|
||||
# Inside initramfs, use Plymouth, otherwise, use read
|
||||
prompt="$device_path matches $hash? [Y/N]"
|
||||
if [ $RELIANT_INITRAMFS -eq $RELIANT_TRUE ]; then
|
||||
if [ "$RELIANT_INITRAMFS" -eq $RELIANT_TRUE ]; then
|
||||
REPLY=$(plymouth ask-question --prompt="$prompt")
|
||||
else
|
||||
read -r -p "$prompt: "
|
||||
|
|
@ -244,6 +246,9 @@ reliant_security_check_devices() {
|
|||
return $RELIANT_SECURITY_FAIL
|
||||
fi
|
||||
done
|
||||
|
||||
# Forward from subshell
|
||||
return $?
|
||||
}
|
||||
|
||||
# Main function
|
||||
|
|
@ -272,7 +277,7 @@ main() {
|
|||
reliant_security_check_network || status_network=$?
|
||||
reliant_security_check_filesystems || status_filesystems=$?
|
||||
reliant_security_check_overlay "$1" || status_overlay=$?
|
||||
reliant_security_check_devices || status_devices=$?
|
||||
reliant_security_check_devices || status_devices=$?
|
||||
|
||||
# Print the report
|
||||
echo "[REPORT]"
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ def parse_qubes_xml(target_pools, qubes_xml):
|
|||
for domain in root.find('domains'):
|
||||
volume_config = domain.find('volume-config')
|
||||
if volume_config is None:
|
||||
continue
|
||||
volume_config = []
|
||||
|
||||
# Detect sys-net and sys-whonix
|
||||
# TODO: use reliant.conf RELIANT_RW_DOMAINS
|
||||
|
|
@ -118,8 +118,6 @@ def parse_qubes_xml(target_pools, qubes_xml):
|
|||
|
||||
# Check VM type
|
||||
if domain.get('class') == 'AdminVM':
|
||||
# dom0
|
||||
|
||||
# Disable update checking
|
||||
features = domain.find('features')
|
||||
for feature in features:
|
||||
|
|
@ -127,6 +125,9 @@ def parse_qubes_xml(target_pools, qubes_xml):
|
|||
features.remove(feature)
|
||||
ElementTree.SubElement(features, 'feature', name='config.default.qubes-update-check').text = ''
|
||||
|
||||
# dom0 does not have volumes, so add it immediately
|
||||
domains['varlibqubes'].append(domain)
|
||||
|
||||
else:
|
||||
# Not dom0, qube ID must be randomized
|
||||
qid = random.randint(1, qubes.config.max_qid)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue