File disk-encryption-tool-1+git20240704.5a6539c.obscpio of Package disk-encryption-tool
07070100000000000081A4000000000000000000000001668640820000013B000000000000000000000000000000000000003900000000disk-encryption-tool-1+git20240704.5a6539c/.editorconfig# EditorConfig configuration for sdbootutil
# http://EditorConfig.org
# Top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file, utf-8 charset
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
indent_style = tab
indent_size = 8
07070100000001000081A4000000000000000000000001668640820000042E000000000000000000000000000000000000003300000000disk-encryption-tool-1+git20240704.5a6539c/LICENSEMIT License
Copyright (c) 2023 Ludwig Nussel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
07070100000002000081A400000000000000000000000166864082000006DC000000000000000000000000000000000000003500000000disk-encryption-tool-1+git20240704.5a6539c/README.mdTool to turn a plain text image into one using LUKS full disk
encryption. There are three modes:
* Directly encrypt a disk image on a host system. The image can then
be deployed somewhere else
* Prime a disk image by adding code to the initrd of the image that
encrypts the image on first boot
* Include the initrd code already when building an image. The image
would then encrypt itself on first boot.
In general the tool is developed with [kiwi](https://github.com/OSInside/kiwi)
in mind. It assumes that the image contains a single root fs using btrfs in the
third partition. Both grub2 and systemd-boot are supported. The tool generates
a
Example to directly encrypt an image:
disk-encryption-tool -v SLE-Micro.x86_64-5.4.0-Default-GM.raw
Example to prime a plain text image to encrypt on first boot:
disk-encryption-tool -v --prime SLE-Micro.x86_64-5.4.0-Default-GM.raw
When run on first boot the tool integrates with
[jeos-firstboot](https://github.com/openSUSE/jeos-firstboot/). The encryption
in initrd deploys an automatically generated recovery key, compatible with
[systemd-cryptenroll](https://www.freedesktop.org/software/systemd/man/latest/systemd-cryptenroll.html).
Later in the real root a jeos-firsboot module then offers to deploy
either the root password or another custom passphrase as well.
Parameters for cryptsetup-reencrypt(8) can be passed via
`/etc/encrypt_options`. One option per line, e.g.
--type=luks1
--iter-time=2000
It's also possible to integrate with combustion. The combustion
script would have to look like this:
#!/bin/bash
# combustion: prepare
if [ "$1" = "--prepare" ]; then
echo 12345 | disk-encryption-tool -v
else
echo root:12345 | chpasswd
fi
07070100000003000081ED0000000000000000000000016686408200003003000000000000000000000000000000000000004000000000disk-encryption-tool-1+git20240704.5a6539c/disk-encryption-tool#!/bin/bash
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2023 SUSE LLC
set -e
shopt -s nullglob
unset "${!LC_@}"
LANG="C.utf8"
export LANG
verbose=
prime=
gen_key=
switched_rw=
cr_name='cr_root'
cr_dev=
blkdev=
blkpart=
partno=
mp=
mounted=
tmpdir=$(mktemp -d -t disk-encryption-tool.XXXXXX)
cleanup()
{
set +e
if [ -n "$mp" ]; then
while read -r i; do
[ "$i" != "$mp" ] || make_ro
umount "$i"
done < <(findmnt -o TARGET -Rn --list "$mp" | tac)
fi
if [ -n "$mounted" ]; then
if [ -e "$tmpdir/mounts" ]; then
# restore previous mounts
while read -r line; do
eval "$line"
mapfile -td, options < <(echo -n "$OPTIONS")
if [ -n "$cr_dev" ] && [ "$SOURCE" = "$blkpart" ]; then
SOURCE="$cr_dev"
fi
mount "$SOURCE" "$TARGET" -t "$FSTYPE" -o "$OPTIONS"
done < "$tmpdir/mounts"
fi
else
[ -e "$cr_dev" ] && cryptsetup close "${cr_dev##*/}"
case "$blkdev" in
/dev/nbd*) qemu-nbd -d "$blkdev" ;;
/dev/loop*) losetup -d "$blkdev" ;;
esac
fi
[ -d "$tmpdir" ] && ! mountpoint -q "$tmpdir/mnt" && rm -rf "$tmpdir"
}
trap cleanup EXIT
helpandquit()
{
cat <<-EOF
Usage: $0 [OPTIONS] IMAGE|BLOCKDEV
Encrypt IMAGE or BLOCKDEV
OPTIONS:
--verbose verbose
--prime add hook scripts to initrd to encrypt on first boot
--partno=N partition number (default 3)
--gen-key generate random recovery key
-h help screen
EOF
exit 0
}
log_info()
{
[ "${verbose:-0}" -gt 0 ] || return 0
echo "$@"
}
err()
{
echo "Error: $*" >&2
exit 1
}
warn()
{
echo "Warning: $*" >&2
}
isdigits()
{
local v="${1:?}"
[ -z "${v//[0-9]*/}" ]
}
settle_umount_events()
{
# Manual umount confuses systemd sometimes because it's async and the
# .mount unit might still be active when the "start" is queued, making
# it a noop, which ultimately leaves /sysroot unmounted
# (https://github.com/systemd/systemd/issues/20329). To avoid that,
# wait until systemd processed the umount events. In a chroot (or with
# SYSTEMD_OFFLINE=1) systemctl always succeeds, so avoid an infinite loop.
if [ "$mounted" = "/sysroot" ] && ! systemctl --quiet is-active does-not-exist.mount; then
while systemctl --quiet is-active sysroot.mount; do sleep 0.5; done
fi
}
read_password()
{
local password2
[ -z "$password" ] || return 0
if ! [ -t 0 ]; then
read -r -s password
return "$?"
fi
while true; do
read -r -s -p "Enter encryption passphrase: " password
echo
if type -p pwscore &>/dev/null; then
echo "$password" | pwscore || continue
fi
read -r -s -p "Confirm encryption passphrase: " password2
echo
if [ "$password" != "$password2" ]; then
echo "Entered passwords don't match"
continue
fi
[ -n "$password" ] || err "No password, no encryption"
break
done
}
encrypt()
{
local encrypt_options=(\
--reduce-device-size 32m \
--progress-frequency=1 \
)
if [ -e "${ENCRYPTION_CONFIG:-/etc/encrypt_options}" ]; then
while read -r op; do
[ "${op//#}" = "$op" ] || continue
encrypt_options+=("$op")
done < "${ENCRYPTION_CONFIG:-/etc/encrypt_options}"
fi
# sle 15 compat code
if type -p cryptsetup-reencrypt &> /dev/null; then
read_password
echo "$password" | cryptsetup-reencrypt --new --type luks1 "${encrypt_options[@]}" "$@" "${blkpart}"
log_info "Encryption done"
log_info "open encrypted image"
echo "$password" | cryptsetup open "${blkpart}" "$cr_name"
else
log_info "encrypt with options ${encrypt_options[*]}"
if [ -n "$password" ]; then
# XXX: hopefully we can use the kernel keyring in the future here
cryptsetup reencrypt --force-password --verbose --encrypt "${encrypt_options[@]}" "$@" "${blkpart}" "$cr_name" <<<"$password"
[ -z "$gen_key" ] || echo '{"type":"systemd-recovery","keyslots":["0"]}' | cryptsetup token import "${blkpart}"
else
cryptsetup reencrypt --batch-mode --verify-passphrase --force-password --verbose --encrypt "${encrypt_options[@]}" "$@" "${blkpart}" "$cr_name"
fi
fi
cr_dev="/dev/mapper/$cr_name"
}
call_dracut()
{
if [ -L "$mp/boot/initrd" ]; then
local initrd kv
initrd="$(readlink "$mp/boot/initrd")"
kv="${initrd#initrd-}"
log_info "create initrd for $kv"
chroot "$mp" dracut --add-drivers dm_crypt -q -f "/boot/$initrd" "$kv" "$@"
elif [ -e "$mp/etc/kernel/entry-token" ]; then
local token kernel kv
read -r token < "$mp/etc/kernel/entry-token"
log_info "token $token"
for initrd in "$mp/boot/efi/$token"/*/initrd-*; do
kv="${initrd%/*}"
kv="${kv##*/}"
initrd="${initrd#"$mp"}"
log_info "create $initrd for $kv"
hostonly_l=no chroot "$mp" dracut -q --reproducible -f "$initrd" "$kv" "$@"
done
else
err "Unsupported boot loader or fs layout"
fi
}
mountstuff()
{
mount -t tmpfs -o size=10m tmpfs "$mp/run"
for i in proc dev sys; do
mount --bind "/$i" "$mp/$i"
done
for i in /.snapshots /boot/efi /boot/writable /var; do
grep -q "\s$i\s" "$mp/etc/fstab" || continue
[ -d "$mp/$i" ] || continue
mountpoint -q "$mp/$i" && continue
mount -T "$mp"/etc/fstab --target-prefix="$mp" "/$i"
done
}
make_rw()
{
local prop
read -r prop < <(btrfs prop get -t s "$mp" ro)
[ "$prop" = "ro=true" ] || return 0
log_info "switch to rw"
btrfs prop set -t s "$mp" ro false
switched_rw=1
}
make_ro()
{
[ -n "$switched_rw" ] || return 0
unset switched_rw
log_info "set ro again"
btrfs prop set -t s "$mp" ro true
}
####### main #######
getopttmp=$(getopt -o hv --long help,verbose,prime,partno:,gen-key -n "${0##*/}" -- "$@")
eval set -- "$getopttmp"
while true ; do
case "$1" in
-h|--help) helpandquit ;;
-v|--verbose) verbose=$((++verbose)); shift ;;
--prime) prime="1"; shift ;;
--partno) partno="$2"; shift 2;;
--gen-key) gen_key="1"; shift;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
[ -z "$1" ] && [ -e /etc/initrd-release ] && set -- /sysroot
[ -n "$1" ] || helpandquit
[ -z "$prime" ] && [ -e "/dev/mapper/$cr_name" ] && err "$cr_name exists. Exit."
if [ -d "$1" ] || [ -b "$1" ]; then
if [ -b "$1" ]; then
blkpart="$1"
else
mountpoint -q "$1" || err "$1 is not a valid mountpoint"
mp="$1"
mounted="$1"
blkpart="$(findmnt -nvo SOURCE "$mp")"
fi
[ -L "/sys/class/block/${blkpart##*/}" ] || err "$blkpart is not a partition"
blkdev="$(readlink -f "/sys/class/block/${blkpart##*/}")"
blkdev="${blkdev%/*}"
blkdev="/dev/${blkdev##*/}"
read -r partno < "/sys/class/block/${blkpart##*/}"/partition
else
[ -n "$partno" ] || warn "--partno not specified, assuming 3"
: "${partno:=3}"
case "${1##*/}" in
*.raw )
log_info "setting up loop device"
blkdev="$(losetup --show -fP "$1")"
log_info "loop device $blkdev"
;;
*.qcow2)
[ -e "/dev/nbd0" ] || modprobe nbd
blkdev=/dev/nbd0
qemu-nbd -c "$blkdev" "$1"
udevadm settle
;;
*) err "Unsupported image" ;;
esac
blkpart="${blkdev}p${partno}"
fi
shift
eval "$(blkid -c /dev/null -o export "$blkpart"|sed 's/^/loop_/')"
[ "$loop_TYPE" != crypto_LUKS ] || { echo "Already encrypted"; exit 0; }
[ "$loop_TYPE" = btrfs ] || err "File system is ${loop_TYPE:-unknown} but only btrfs is supported"
if [ -z "$mounted" ]; then
log_info "mounting fs"
mkdir -p "$tmpdir/mnt"
mount -t btrfs -o rw "${blkpart}" "$tmpdir/mnt"
mp="$tmpdir/mnt"
else
mountpoint -q "$mp" || err "$mp is not mounted"
findmnt -o SOURCE,TARGET,FSTYPE,OPTIONS -Rvn --pairs "$mp" > "$tmpdir/mounts"
mount -o remount,rw "$mp"
fi
if [ -n "$prime" ]; then
mkdir -p "$tmpdir/overlay-w"
dst="$tmpdir/overlay/95disk-encryption-tool"
mkdir -p "$dst"
for i in disk-encryption-tool disk-encryption-tool-dracut module-setup.sh \
disk-encryption-tool-dracut.service generate-recovery-key; do
cp "${0%/*}/$i" "$dst/$i"
done
if [ -e "${ENCRYPTION_CONFIG:-/etc/encrypt_options}" ]; then
cp "${ENCRYPTION_CONFIG:-/etc/encrypt_options}" "$dst/encrypt_options"
export ENCRYPTION_CONFIG="/usr/lib/dracut/modules.d/95disk-encryption-tool/encrypt_options"
fi
make_rw
mountstuff
# dirty
if [ -d "$mp/usr/share/jeos-firstboot/modules" ]; then
install -D -m 644 "${0%/*}/jeos-firstboot-diskencrypt-override.conf" "$mp/usr/lib/systemd/system/jeos-firstboot.service.d/jeos-firstboot-diskencrypt-override.conf"
cp "${0%/*}/jeos-firstboot-enroll" "$mp/usr/share/jeos-firstboot/modules/enroll"
fi
mount -t overlay overlay \
-o lowerdir="$mp/usr/lib/dracut/modules.d/,upperdir=$tmpdir/overlay,workdir=$tmpdir/overlay-w" \
"$mp/usr/lib/dracut/modules.d/"
call_dracut
exit 0
fi
read -r minsize bytes _rest < <(btrfs inspect-internal min-dev-size "$mp")
isdigits "$minsize" || err "Failed to read minimum btrfs size"
[ "$bytes" = 'bytes' ] || err "Failed to read minimum btrfs size"
log_info "resizing fs"
btrfs filesystem resize "$minsize" "$mp"
if [ -e "$tmpdir/mounts" ]; then
# subshell intentional here
tac "$tmpdir/mounts" | while read -r line; do
eval "$line"
umount "$TARGET"
done
else
umount "$mp"
fi
unset mp
settle_umount_events
# shrink partition to a minimum so reencryption doesn't write everything
log_info "resizing partition"
echo "size=$((minsize/1024+32*1024))KiB" | sfdisk -q -N "$partno" "$blkdev"
udevadm settle
if [ -n "$gen_key" ]; then
read -r password < <(generate-recovery-key)
echo -e "Recovery key: \e[1m$password\e[m"
if [ -e /etc/initrd-release ]; then
read -r key_id < <(echo -n "$password" | keyctl padd user cryptenroll @u)
fi
fi
echo "Encrypting..."
encrypt "$@"
log_info "grow partition again"
echo ", +" | sfdisk --no-reread -q -N "$partno" "$blkdev"
if [ -e /etc/initrd-release ]; then
# seems to be the only way to tell the kernel about a specific partition change
partx -u --nr "$partno" "$blkdev" || :
# now resize the mapping. For some reason cryptsetup wants a passphrase. Hack
# around this by installing a token that makes it read the key we installed
# before, then remove the token again o_O
cryptsetup token add --key-slot 0 --key-description cryptenroll --token-id 9 "$blkpart"
cryptsetup resize "$cr_name" < /dev/null
cryptsetup token remove --token-id 9 "$blkpart"
fi
if [ -z "$mounted" ]; then
mount -o rw "$cr_dev" "/mnt"
mp="/mnt"
else
read -r line < "$tmpdir/mounts"
eval "$line"
mapfile -td, options < <(echo -n "$OPTIONS")
for ((i=0;i<${#options};++i)); do [ "${options[i]}" = ro ] && options[i]=rw; done
OPTIONS="$(IFS=, eval echo '"${options[*]}"')"
[ "$SOURCE" = "$blkpart" ] && SOURCE="$cr_dev"
mount "$cr_dev" "$TARGET" -t "$FSTYPE" -o "$OPTIONS"
mp="$TARGET"
fi
log_info "resizing fs to max again"
btrfs filesystem resize max "$mp"
make_rw
declare loop_UUID
eval "$(blkid -c /dev/null -o export "$blkpart"|sed 's/^/loop_/')"
if [ -n "$loop_UUID" ]; then
echo "$cr_name /dev/disk/by-uuid/$loop_UUID none x-initrd.attach" > "$mp"/etc/crypttab
else
warn "Can't determine device UUID. Can't generate crypttab"
fi
mountstuff
if grep -q "LOADER_TYPE.*grub2" "$mp"/etc/sysconfig/bootloader; then
log_info "Update bootloader"
echo GRUB_ENABLE_CRYPTODISK=y >> "$mp"/etc/default/grub
sed -i -e 's/^LOADER_TYPE=.*/LOADER_TYPE="grub2"/' "$mp"/etc/sysconfig/bootloader
chroot "$mp" update-bootloader --reinit
sed -i -e 's/^LOADER_TYPE=.*/LOADER_TYPE="grub2-efi"/' "$mp"/etc/sysconfig/bootloader
chroot "$mp" update-bootloader --reinit
mv "$mp/boot/grub2/grub.cfg" "$mp/boot/grub2/grub.cfg.bak"
cat > "$mp/boot/grub2/grub.cfg" <<-'EOF'
set linux=linux
set initrd=initrd
if [ "${grub_cpu}" = "x86_64" -o "${grub_cpu}" = "i386" ]; then
if [ "${grub_platform}" = "efi" ]; then
set linux=linuxefi
set initrd=initrdefi
fi
fi
export linux initrd
EOF
sed -e 's/linuxefi/$linux/;s/initrdefi/$initrd/' < "$mp/boot/grub2/grub.cfg.bak" >> "$mp/boot/grub2/grub.cfg"
rm "$mp/boot/grub2/grub.cfg.bak"
elif [ -e "$mp/etc/kernel/entry-token" ]; then
: # sd-boot
else
log_info "unsupported boot loader"
grep LOADER_TYPE "$mp"/etc/sysconfig/bootloader
fi
# A new initrd is created as side effect of the enrolment
# (jeos-firtboot module), as this calls sdbootutil
make_ro
echo "Image encryption completed"
07070100000004000081ED0000000000000000000000016686408200000480000000000000000000000000000000000000004700000000disk-encryption-tool-1+git20240704.5a6539c/disk-encryption-tool-dracut#!/bin/sh
exec < /dev/console >/dev/console 2>&1
type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
# get systemd credential
# https://systemd.io/CREDENTIALS/
get_credential()
{
local var="${1:?}"
local name="${2:?}"
[ -n "$CREDENTIALS_DIRECTORY" ] || return 1
[ -e "$CREDENTIALS_DIRECTORY/$name" ] || return 1
read -r "$var" < "$CREDENTIALS_DIRECTORY/$name" || [ -n "${!var}" ]
}
encrypt=
if get_credential encrypt rd.encrypt && [ "$encrypt" = "no" ]; then
exit 0
fi
# check whether encryption was explicitly turned off
if ! getargbool 1 rd.encrypt; then
exit 0
fi
# XXX: this is so dirty
systemctl start sysroot.mount
mount --target-prefix /sysroot --fstab /sysroot/etc/fstab /var
if [ ! -e /sysroot/var/lib/YaST2/reconfig_system ]; then
echo "system already configured, no encryption"
umount /sysroot/var
exit 0
fi
umount /sysroot/var
# silence systemd
kill -SIGRTMIN+21 1
echo -ne '\n\n\a'
read -n1 -s -r -t 10 -p "*** Press ESC to prevent encrypting the disk" inhibitor
echo
if [ "$inhibitor" != $'\e' ]; then
/usr/bin/disk-encryption-tool -v --gen-key || die "Encryption failed"
fi
# turn messages on again
kill -SIGRTMIN+20 1
07070100000005000081A40000000000000000000000016686408200000342000000000000000000000000000000000000004F00000000disk-encryption-tool-1+git20240704.5a6539c/disk-encryption-tool-dracut.service[Unit]
Description=Encrypt root disk
DefaultDependencies=false
# /sysroot needs to be available, but it's temporarily stopped
# for remounting so a direct requirement is not possible
Requires=initrd-root-device.target
After=initrd-root-device.target
After=combustion.service
# After ignition completed its stuff
After=ignition-complete.target
# So that /etc/fstab's x-initrd.mount entries are read (again) later
Before=initrd-parse-etc.service
Conflicts=initrd-switch-root.target umount.target
Conflicts=dracut-emergency.service emergency.service emergency.target
# Without this it goes into an endless loop on failure
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
KeyringMode=shared
ExecStart=/usr/bin/disk-encryption-tool-dracut
ImportCredential=rd.encrypt
[Install]
RequiredBy=firstboot.target
07070100000006000081A40000000000000000000000016686408200000C16000000000000000000000000000000000000004500000000disk-encryption-tool-1+git20240704.5a6539c/disk-encryption-tool.spec#
# spec file for package disk-encryption-tool
#
# Copyright (c) 2024 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
# icecream 0
%if 0%{?_build_in_place}
%define git_version %(git log '-n1' '--date=format:%Y%m%d' '--no-show-signature' "--pretty=format:+git%cd.%h")
BuildRequires: git-core
%else
# this is required for obs' source validator. It's
# 20-files-present-and-referenced ignores all conditionals. So the
# definition of git_version actually happens always.
%define git_version %{nil}
%endif
Name: disk-encryption-tool
Version: 84.87%{git_version}
Release: 0
Summary: Tool to reencrypt kiwi raw images
License: MIT
URL: https://github.com/lnussel/disk-encryption-tool
Source: disk-encryption-tool-%{version}.tar
Requires: cryptsetup
Requires: keyutils
Requires: pcr-oracle
# something needs to require it. Can be us.
Requires: tpm2.0-tools
Requires: qrencode
ExclusiveArch: aarch64 ppc64le riscv64 x86_64
%description
Convert a plain text kiwi image into one with LUKS full disk
encryption. Supports both raw and qcow2 images. It assumes that the
third partition is the root fs using btrfs.
After encrypting the disk, the fs is mounted and a new initrd
created as well as the grub2 config adjusted.
%prep
%setup -q
%build
%install
mkdir -p %buildroot/usr/lib/dracut/modules.d/95disk-encryption-tool
for i in disk-encryption-tool{,-dracut,-dracut.service} module-setup.sh generate-recovery-key; do
cp "$i" %buildroot/usr/lib/dracut/modules.d/95disk-encryption-tool/"$i"
done
mkdir -p %buildroot/usr/bin
ln -s ../lib/dracut/modules.d/95disk-encryption-tool/disk-encryption-tool %buildroot/usr/bin
ln -s ../lib/dracut/modules.d/95disk-encryption-tool/generate-recovery-key %buildroot/usr/bin
install -D -m 644 jeos-firstboot-diskencrypt-override.conf \
%{buildroot}/usr/lib/systemd/system/jeos-firstboot.service.d/jeos-firstboot-diskencrypt-override.conf
install -D -m 644 jeos-firstboot-enroll %buildroot/usr/share/jeos-firstboot/modules/enroll
%files
%license LICENSE
/usr/bin/disk-encryption-tool
/usr/bin/generate-recovery-key
%dir /usr/lib/dracut
%dir /usr/lib/dracut/modules.d
/usr/lib/dracut/modules.d/95disk-encryption-tool
%dir /usr/share/jeos-firstboot
%dir /usr/share/jeos-firstboot/modules
/usr/share/jeos-firstboot/modules/enroll
%dir /usr/lib/systemd/system/jeos-firstboot.service.d
/usr/lib/systemd/system/jeos-firstboot.service.d/jeos-firstboot-diskencrypt-override.conf
%changelog
07070100000007000081ED00000000000000000000000166864082000001C9000000000000000000000000000000000000004100000000disk-encryption-tool-1+git20240704.5a6539c/generate-recovery-key#!/bin/bash
set -e
modhex=('c' 'b' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'n' 'r' 't' 'u' 'v')
mapfile -t raw_key < <(hexdump -v --format '1/1 "%u\n"' -n 32 /dev/random)
[ "${#raw_key[@]}" = 32 ]
key=""
for ((i=0;i<"${#raw_key[@]}";++i)); do
[ "$i" -gt 0 ] && [ "$((i%4))" -eq 0 ] && key="$key-"
c="${raw_key[i]}"
key="$key${modhex[$((c>>4))]}${modhex[$((c&15))]}"
done
[ -x /usr/bin/qrencode ] && [ -t 1 ] && echo -n "$key" | qrencode -t utf8i
echo "$key"
07070100000008000081A4000000000000000000000001668640820000001D000000000000000000000000000000000000005400000000disk-encryption-tool-1+git20240704.5a6539c/jeos-firstboot-diskencrypt-override.conf[Service]
KeyringMode=shared
07070100000009000081A4000000000000000000000001668640820000222F000000000000000000000000000000000000004100000000disk-encryption-tool-1+git20240704.5a6539c/jeos-firstboot-enroll#!/bin/bash
crypt_keyid=""
crypt_pw=""
crypt_tpm_pin=""
# for pin
cryptenroll_tpm_extra_args=()
with_fido2=
with_tpm2=
luks2_devices=()
# After the enrolling, other tools can find this list in
# /etc/sysconfig/fde-tools
if [ $(sdbootutil bootloader) = "systemd-boot" ]; then
FDE_SEAL_PCR_LIST="0,2,4,7,9"
elif [ $(sdbootutil bootloader) = "grub2" ]; then
FDE_SEAL_PCR_LIST="0,2,4,7,8,9"
else
d --msgbox "Error: Bootloader not detected" 0 0
fi
have_luks2()
{
[ "${#luks2_devices[@]}" -gt 0 ]
}
detect_luks2()
{
local dev fstype
[ -z "$luks2_devices" ] || return 0
while read -r dev fstype; do
[ "$fstype" = 'crypto_LUKS' ] || continue
cryptsetup isLuks --type luks2 "$dev" || continue
luks2_devices+=("$dev")
done < <(lsblk --noheadings -o PATH,FSTYPE)
have_luks2
}
# exit early without defining any helper functions if there are no luks devices
detect_luks2 || return 0
enroll_systemd_firstboot() {
[ -e /usr/bin/systemd-cryptenroll ] || return 0
crypt_keyid="$(keyctl id %user:cryptenroll 2> /dev/null)" || return 0
[ -n "$crypt_keyid" ] || return 0
welcome_screen_with_console_switch
local has_fido2=${JEOS_HAS_FIDO2:-}
local has_tpm2=
[ -z "$(systemd-cryptenroll --fido2-device=list 2>/dev/null)" ] || has_fido2=1
if [ -e '/sys/class/tpm/tpm0' ]; then
if have_pcrlock && ! is_pcr_oracle; then
has_tpm2=lock
elif have_pcr_oracle; then
has_tpm2=oracle
fi
fi
while true; do
local list=()
if [ -z "$with_fido2" ] && [ -z "$with_tpm2" ] && [ -n "$has_fido2" ]; then
list+=('FIDO2' $'Enroll FIDO2 token')
fi
if [ -z "$with_tpm2" ] && [ -z "$with_fido2" ] && [ -n "$has_tpm2" ]; then
list+=('TPM2' $'Enroll TPM2 based token' 'TPM2_interactive' 'Enroll TPM2 based token with PIN')
fi
if [ -z "$crypt_pw" ]; then
if [ -n "$password" ]; then
list+=('root' $'Enroll root password')
fi
list+=('password' $'Enroll extra password')
fi
[ -n "$list" ] || break
list+=('done' $'Done')
d --no-tags --default-item "${list[0]}" --menu $"Disk Encryption" 0 0 "$(menuheight ${#list[@]})" "${list[@]}"
if [ "$result" = 'done' ]; then
if [ -z "$crypt_pw" ] && [ -z "$with_fido2" ] && [ -z "$with_tpm2" ] && [ -z "$is_jeos_config" ]; then
d_styled --yesno $"Neither password, TPM2 nor FIDO2 entrolled. Unlocking disk will only work with recovery key. Is this intended?" 0 0 || continue
fi
break;
elif [ "$result" = 'FIDO2' ]; then
with_fido2=1
elif [ "$result" = 'TPM2' ]; then
with_tpm2="$has_tpm2"
elif [ "$result" = 'TPM2_interactive' ]; then
while true; do
d --insecure --passwordbox $"Enter new PIN (actually just passphrase)" 0 0
if [ -z "$result" ]; then
d_styled --yesno $"Retry?" 0 0 || break
continue
fi
crypt_tpm_pin="$result"
d --insecure --passwordbox $"Confirm PIN" 0 0
[ "$crypt_tpm_pin" != "$result" ] || { with_tpm2="$has_tpm2"; break; }
d --msgbox $"PINs don't match. Try again" 0 0
done
elif [ "$result" = 'root' ]; then
crypt_pw="$password"
elif [ "$result" = 'password' ]; then
while true; do
d --insecure --passwordbox $"Enter encryption password" 0 0
if [ -z "$result" ]; then
d --aspect 29 --msgbox $"No encryption password set. You can add more keys manually using systemd-cryptenroll." 0 0
break
fi
crypt_pw="$result"
d --insecure --passwordbox $"Confirm encryption password" 0 0
[ "$crypt_pw" != "$result" ] || break
d --msgbox $"Passwords don't match. Try again" 0 0
done
else
d --msgbox "Error: $result" 0 0
fi
done
return 0
}
enroll_fido2() {
local dev="$1"
echo "Enrolling with FIDO2: $dev"
# The password is read from "cryptenroll" kernel keyring
run systemd-cryptenroll --fido2-device=auto "$dev"
}
generate_rsa_key() {
[ -z "$dry" ] && mkdir -p /etc/systemd
run pcr-oracle \
--rsa-generate-key \
--private-key /etc/systemd/tpm2-pcr-private-key.pem \
--public-key /etc/systemd/tpm2-pcr-public-key.pem \
store-public-key
}
enroll_tpm2_pcr_oracle() {
local dev="$1"
echo "Enrolling with TPM2 (pcr-oracle): $dev"
# The password is read from "cryptenroll" kernel keyring
# XXX: Wipe is separated by now (possible systemd bug)
run systemd-cryptenroll \
--wipe-slot=tpm2 \
"$dev"
NEWPIN="$crypt_tpm_pin" run systemd-cryptenroll \
--tpm2-device=auto \
"${cryptenroll_tpm_extra_args[@]}" \
--tpm2-public-key=/etc/systemd/tpm2-pcr-public-key.pem \
--tpm2-public-key-pcrs="$FDE_SEAL_PCR_LIST" \
"$dev"
}
enroll_tpm2_pcrlock() {
local dev="$1"
echo "Enrolling with TPM2 (pcrlock): $dev"
# The password is read from "cryptenroll" kernel keyring
# XXX: Wipe is separated by now (possible systemd bug)
run systemd-cryptenroll \
--wipe-slot=tpm2 \
"$dev"
# Note that the PCRs are now not stored in the LUKS2 header
NEWPIN="$crypt_tpm_pin" run systemd-cryptenroll \
--tpm2-device=auto \
"${cryptenroll_tpm_extra_args[@]}" \
--tpm2-pcrlock=/var/lib/systemd/pcrlock.json \
"$dev"
}
update_crypttab_options() {
# This version will share the same options for all crypto_LUKS
# devices. This imply that all of them will be unlocked by the
# same TPM2, or the same FIDO2 key
local options="$1"
# TODO: this needs to be unified with disk-encryption-tool
local crypttab
if [ -z "$dry" ]; then
crypttab="$(mktemp -t disk-encryption-tool.crypttab.XXXXXX)"
else
crypttab=/dev/stdout
fi
echo "# File created by jeos-firstboot-enroll. Comments will be removed" > "$crypttab"
local name
local device
local key
local opts
while read -r name device key opts; do
[[ "$name" = \#* ]] && continue
echo "$name $device $key $options" >> "$crypttab"
done < /etc/crypttab
run mv "$crypttab" /etc/crypttab
run chmod 644 /etc/crypttab
}
have_pcrlock() {
[ -e /usr/lib/systemd/systemd-pcrlock ]
}
have_pcr_oracle() {
[ -e /usr/bin/pcr-oracle ]
}
is_pcr_oracle() {
have_pcr_oracle && \
[ -e /etc/systemd/tpm2-pcr-public-key.pem ] && \
[ -e /etc/systemd/tpm2-pcr-private-key.pem ]
}
write_issue_file() {
if [ -e '/usr/sbin/issue-generator' ] && [ -z "$dry" ]; then
mkdir -p "/run/issue.d/"
issuefile="/run/issue.d/90-diskencrypt.conf"
else
issuefile='/dev/stdout'
fi
echo -ne "Encryption recovery key:\n " > "$issuefile"
keyctl pipe "$crypt_keyid" >> "$issuefile"
echo -e "\n" >> "$issuefile"
if [ -x /usr/bin/qrencode ]; then
echo "You can also scan it with your mobile phone:" >> "$issuefile"
keyctl pipe "$crypt_keyid" | qrencode -t utf8i >> "$issuefile"
fi
run issue-generator
[ -n "$dry" ] || cat "$issuefile"
}
add_password() {
[ -n "$crypt_pw" ] || return 0
local dev
for dev in "${luks2_devices[@]}"; do
echo "adding password to $dev"
echo -n "$crypt_pw" | run cryptsetup luksAddKey --verbose --batch-mode --force-password --key-file <(keyctl pipe "$crypt_keyid") "$dev"
done
}
enroll_post() {
[ -e /usr/bin/systemd-cryptenroll ] || return 0
[ -n "$crypt_keyid" ] || return 0
write_issue_file
add_password
enroll_tpm_and_fido
}
enroll_tpm_and_fido() {
# For now is a first step before moving into fde-tools
local fde_cfg='/etc/sysconfig/fde-tools'
if [ -e "$fde_cfg" ]; then
. "$fde_cfg"
else
[ -z "$dry" ] || fde_cfg=/dev/stdout
echo "FDE_SEAL_PCR_LIST=${FDE_SEAL_PCR_LIST}" > "$fde_cfg"
fi
local dev
local fstype
local crypttab_options="x-initrd.attach"
# Generate first the crypttab + initrd, so the predictions can be
# done in case of pcrlock
if [ "$with_fido2" = '1' ]; then
crypttab_options+=",fido2-device=auto"
elif [ -n "$with_tpm2" ]; then
crypttab_options+=",tpm2-device=auto"
fi
update_crypttab_options "$crypttab_options"
if [ "$with_tpm2" = 'oracle' ]; then
generate_rsa_key
else
# sdbootutil will generate predictions for pcrlock
SDB_ADD_INITIAL_COMPONENT=1 run sdbootutil add-all-kernels --no-reuse-initrd
fi
if [ "$with_fido2" = '1' ]; then
for dev in "${luks2_devices[@]}"; do
enroll_fido2 "$dev"
done
elif [ -n "$with_tpm2" ]; then
if [ -n "$crypt_tpm_pin" ]; then
# XXX ./src/cryptenroll/cryptenroll-tpm2.c lacks accept cached
#echo -n "$crypt_tpm_pin" | run keyctl padd user tpm2-pin @u
cryptenroll_tpm_extra_args+=(--tpm2-with-pin=1)
fi
for dev in "${luks2_devices[@]}"; do
if [ "$with_tpm2" = 'lock' ]; then
enroll_tpm2_pcrlock "$dev"
else
enroll_tpm2_pcr_oracle "$dev"
fi
done
fi
if [ "$with_tpm2" = 'oracle' ]; then
# with pcr-oracle we pick up settings from the luks header
run sdbootutil add-all-kernels --no-reuse-initrd
fi
}
enroll_jeos_config() {
is_jeos_config=1
d --insecure --passwordbox $"Enter decryption password" 0 0
[ -n "$result" ] || return 0
echo -n "$result" | keyctl padd user cryptenroll @u
enroll_systemd_firstboot
add_password
enroll_tpm_and_fido
}
0707010000000A000081ED00000000000000000000000166864082000003F5000000000000000000000000000000000000003B00000000disk-encryption-tool-1+git20240704.5a6539c/module-setup.sh#!/bin/bash
# called by dracut
check() {
require_any_binary cryptsetup || return 1
return 0
}
# called by dracut
depends() {
echo "crypt"
return 0
}
# called by dracut
install() {
instmods dmi_sysfs # for systemd credentials via smbios
inst_multiple -o cryptsetup-reencrypt
inst_multiple cryptsetup btrfs mktemp getopt mountpoint findmnt sfdisk tac sed hexdump keyctl partx
inst_script "$moddir"/disk-encryption-tool /usr/bin/disk-encryption-tool
inst_script "$moddir"/disk-encryption-tool-dracut /usr/bin/disk-encryption-tool-dracut
inst_script "$moddir"/generate-recovery-key /usr/bin/generate-recovery-key
for service in "disk-encryption-tool-dracut.service"; do
inst_simple "${moddir}/$service" "${systemdsystemunitdir}/$service"
$SYSTEMCTL -q --root "$initdir" enable "$service"
#$SYSTEMCTL -q --root "$initdir" enable "debug-shell.service"
done
: "${ENCRYPTION_CONFIG:=/etc/encrypt_options}"
[ -e "$ENCRYPTION_CONFIG" ] && inst_simple "$ENCRYPTION_CONFIG" "/etc/encrypt_options"
}
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!65 blocks