Skip to content
Snippets Groups Projects
Commit ec5caffc authored by ping's avatar ping
Browse files

Migrate to binary for disk decryption in initramfs

parent 2c9041f6
No related branches found
No related tags found
No related merge requests found
Showing
with 187 additions and 65 deletions
......@@ -2,3 +2,5 @@
.env*
cache/
config/02-customisation/etc/NetworkManager/system-connections/wifi.nmconnection
tools/unlocker-advanced.c
config/03-post_install/7000-unlocker-advanced.sh*
ARG DEBIAN_FRONTEND=noninteractive
FROM ubuntu:22.04
ENV archive=go1.22.6.linux-amd64.tar.gz
ENV PATH=$PATH:/usr/local/go/bin
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y gcc pkg-config git wget make ca-certificates libglfw3-dev libxcursor-dev libxinerama-dev libxi-dev libxxf86vm-dev upx-ucl curl cryptsetup squashfs-tools fakechroot debootstrap xorriso mtools dosfstools gnutls-bin
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive \
apt-get install -y gcc \
pkg-config \
git \
wget \
make \
ca-certificates \
libglfw3-dev \
libxcursor-dev \
libxinerama-dev \
libxi-dev \
libxxf86vm-dev \
upx-ucl \
curl \
cryptsetup \
squashfs-tools \
fakechroot \
debootstrap \
xorriso \
mtools \
dosfstools \
gnutls-bin \
build-essential \
unzip \
libykpers-1-dev \
libyubikey-dev \
libcryptsetup-dev \
libssl-dev \
&& apt-get clean
RUN git clone https://github.com/limine-bootloader/limine.git --branch=v8.x-binary --depth=1 /opt/limine && \
cd /opt/limine && \
make && \
cp /opt/limine/limine /bin/
RUN git config --global --add safe.directory /data
RUN wget https://go.dev/dl/$archive && tar -C /usr/local -xzf $archive
# This part is used to compile the dependencies so that you don't have to do it every time you run the build.sh script (it saves around 2.5 minutes).
WORKDIR /nexus
RUN wget https://go.dev/dl/$archive && tar -C /usr/local -xzf $archive
RUN git config --global --add safe.directory /nexus
COPY src src
COPY Makefile .
......@@ -24,3 +52,9 @@ COPY config config
RUN cd config/certs && ./gen-cert.sh ca.info nexus-server.info /nexus/certs
RUN make build_nexus-exam SERVER='127.0.0.1:1077' CERT='certs/ca-cert.pem' EXAM_USER='user' EXAM_PWD='pwd'
WORKDIR /tigress
COPY live_exam_os/tigress_4.0.10-1_all.deb.zip .
RUN unzip tigress_4.0.10-1_all.deb.zip
RUN dpkg --force-architecture -i tigress_4.0.10-1_all.deb
......@@ -9,7 +9,6 @@ xserver-xorg
xserver-xorg-input-libinput
xinit
xfce4
xfce4-terminal
systemd
policykit-1
adwaita-icon-theme
......@@ -21,6 +20,9 @@ iptables
ufw
rfkill
wpasupplicant
yubikey-personalization
shim-signed
grub-efi-amd64-signed
build-essential
libykpers-1-dev
libyubikey-dev
libcryptsetup-dev
......@@ -3,5 +3,5 @@
set -e
. /usr/share/initramfs-tools/hook-functions
copy_exec /usr/bin/ykchalresp /bin/ykchalresp
copy_exec /etc/challenge /scripts/challenge
copy_exec /etc/unlock_luks /scripts/unlock_luks
copy_exec /lib/x86_64-linux-gnu/libykpers-1.so.* /lib/x86_64-linux-gnu/
......@@ -24,23 +24,4 @@ if [ ! $exit_code -eq 0 ]; then
mount_and_switch /cdrom/squash.rootfs
fi
echo "Waiting for Yubikey."
while true; do
output=$(ykchalresp -2 -i /scripts/challenge 2>&1)
exit_code=$?
if read -t 1 -n 1 input && [ "$input" = "p" ]; then
echo ""
decrypt_with_passphrase /cdrom/squash.rootfs
continue
fi
if [ "$exit_code" -eq 1 ]; then
sleep 1
continue
fi
decrypt_with_challenge /cdrom/squash.rootfs $output
done
decrypt_mount_and_switch
......@@ -17,21 +17,4 @@ if [ ! $exit_code -eq 0 ]; then
mount_and_switch $SQUASH_FILE
fi
echo "Waiting for Yubikey"
while true; do
output=$(ykchalresp -2 -i /scripts/challenge 2>&1)
exit_code=$?
if read -t 1 -n 1 input && [ "$input" = "p" ]; then
echo ""
decrypt_with_passphrase $SQUASH_FILE
continue
fi
if [ "$exit_code" -eq 1 ]; then
sleep 1
continue
fi
decrypt_with_challenge $SQUASH_FILE $output
done
decrypt_mount_and_switch
......@@ -14,6 +14,27 @@ mount_and_switch() {
exec switch_root /newroot /sbin/init
}
decrypt_mount_and_switch() {
echo "Waiting for Yubikey."
while true; do
output=$(/scripts/unlock_luks)
exit_code=$?
if read -t 1 -n 1 input && [ "$input" = "p" ]; then
echo ""
decrypt_with_passphrase /cdrom/squash.rootfs
continue
fi
if [ "$exit_code" -eq 1 ]; then
sleep 1
continue
fi
mount_and_switch /dev/mapper/data
done
}
decrypt_with_passphrase() {
SQUASHFS_LUKS=$1
cryptsetup open $1 data
......@@ -26,18 +47,6 @@ decrypt_with_passphrase() {
echo "Wrong passphrase"
}
decrypt_with_challenge() {
SQUASHFS_LUKS=$1
echo -n "$2" | cryptsetup open $SQUASHFS_LUKS data
exit_code=$?
if [ "$exit_code" -eq 0 ]; then
mount_and_switch /dev/mapper/data
fi
echo "Decryption error, possibly wrong Yubikey"
}
mount_fs() {
SQUASHFS_PATH=$1
mkdir -p /newroot/{home, run, tmp, var/log, var/tmp} /rw_home /squash
......@@ -63,7 +72,6 @@ mount_fs() {
mount --bind /rw_home /newroot/home
}
find_active_interface() {
for iface in $(ls /sys/class/net); do
if [ "$iface" = "lo" ]; then
......
#/bin/bash
. tools/functions.sh
echo " [Adding challenge file...]"
echo "$CHALLENGE" > $ROOTFS_DIR/etc/challenge
#!/bin/bash
. tools/functions.sh
echo " [Compile unlocker...]"
sed "s/DUMMY_CHALLENGE/$CHALLENGE/g" tools/unlocker.c > /tmp/unlocker.c
run_command gcc -o /tmp/unlock_luks /tmp/unlocker.c -I/usr/include/ykpers-1 -lykpers-1 -lyubikey -lcryptsetup
run_command strip /tmp/unlock_luks
run_command cp /tmp/unlock_luks $ROOTFS_DIR/etc/unlock_luks
......@@ -4,4 +4,3 @@
echo " [Update initramfs...]"
run_command_chroot update-initramfs -u
check_exit_code $? "Error during initramfs generation"
File added
......@@ -77,3 +77,20 @@ check_dependencies() {
exit 1
fi
}
find_latest_library() {
local library_name=$1
local library_files
library_files=$(find /$ROOTFS_DIR -name "$library_name" 2>/dev/null)
if [ -z "$library_files" ]; then
echo "No version available of $library_name."
return 1
fi
local latest_library
latest_library=$(echo "$library_files" | sort -r | head -n 1)
realpath "$latest_library"
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ykpers-1/ykpers.h>
#include <yubikey.h>
#include <libcryptsetup.h>
#define LUKS_DEVICE "/cdrom/squash.rootfs"
#define LUKS_NAME "data"
int unlock_luks(const char *device, const char *name, const char *key, size_t key_size) {
struct crypt_device *cd;
if (crypt_init(&cd, device) < 0) {
fprintf(stderr, "Error: Cannot initialize cryptsetup\n");
return -1;
}
if (crypt_load(cd, CRYPT_LUKS2, NULL) < 0) {
fprintf(stderr, "Error: Cannot load LUKS header\n");
crypt_free(cd);
return -1;
}
if (crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, key, strlen(key), CRYPT_ACTIVATE_ALLOW_DISCARDS) < 0) {
fprintf(stderr, "Error: Cannot decrypt device\n");
crypt_free(cd);
return -1;
}
crypt_free(cd);
return 0;
}
int main() {
YK_KEY *yk = NULL;
unsigned char response[64];
unsigned int response_len = sizeof(response);
char *hex_response = malloc(41);
unsigned char challenge[64] = "DUMMY_CHALLENGE\n";
if (!hex_response) {
fprintf(stderr, "Error: Failed memory allocation\n");
free(hex_response);
return 1;
}
if (!yk_init()) {
fprintf(stderr, "Error: Cannot initialize libykpers\n");
free(hex_response);
return 1;
}
yk = yk_open_first_key();
if (!yk) {
yk_release();
free(hex_response);
return 1;
}
if (!yk_challenge_response(yk, SLOT_CHAL_HMAC1, YK_FLAG_MAYBLOCK, sizeof(challenge), challenge, response_len, response)) {
fprintf(stderr, "Error: challenge-response issue\n");
yk_close_key(yk);
yk_release();
free(hex_response);
return 1;
}
for (int i = 0; i < 20; i++) {
sprintf(hex_response + (i * 2), "%02x", response[i]);
}
hex_response[40] = '\0';
yk_close_key(yk);
yk_release();
if (unlock_luks(LUKS_DEVICE, LUKS_NAME, hex_response, strlen(hex_response)) != 0) {
fprintf(stderr, "Error: Cannot decrypt device\n");
return 1;
}
free(hex_response);
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment