Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for unlocking multi-device root #57

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions initramfs-init.in
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ myopts="alpine_dev autodetect autoraid chart cryptroot cryptdm cryptheader crypt
pkgs quiet root_size root usbdelay ip alpine_repo apkovl alpine_start splash
blacklist overlaytmpfs rootfstype rootflags nbd resume s390x_net dasd ssh_key
BOOTIF zfcp"
for i in `seq 0 9`; do
myopts="$myopts cryptroot$i cryptdm$i cryptheader$i cryptoffset$i
cryptdiscards$i cryptkey$i"
done

for opt; do
case "$opt" in
Expand Down Expand Up @@ -487,6 +491,72 @@ if [ -n "$KOPT_cryptroot" ]; then
fi
fi

(
# Helper functions to avoid obscuring logic with so many evals
for var in cryptroot cryptdiscards cryptdm cryptoffset cryptheader cryptkey; do
eval "$var() { eval 'printf -- %s \"\$KOPT_$var'\$1'\"'; }"
done
for i in `seq 0 9`; do
[ -n "$(cryptroot $i)" ] || continue
any=true

ebegin "Opening encrypted device $(cryptroot $i)"

opts="-c $(cryptroot $i)"

if [ "$(cryptdiscards $i)" = "yes" ]; then
opts="$opts -D"
fi

if [ -n "$(cryptdm $i)" ]; then
name="$(cryptdm $i)"
else
name=$(
dd if=/dev/urandom bs=4096 count=1 2>/dev/null \
| sha1sum | tr -d \ -
)
cat >&2 <<-EOF
WARNING: cryptsetup does not work without having a device name set. You should
provide one using cryptdm$i=. Using temporary name:
$name.
EOF
fi
opts="$opts -m $name"

if [ -n "$(cryptheader $i)" ]; then
opts="$opts -H $(cryptheader $i)"
fi

if [ -n "$(cryptoffset $i)" ]; then
opts="$opts -o $(cryptoffset $i)"
fi

if [ "$(cryptkey $i)" = "yes" ]; then
opts="$opts -k /crypto_keyfile.bin"
elif [ -n "$(cryptkey $i)" ]; then
opts="$opts -k $(cryptkey $i)"
fi

nlplug-findfs $opts -p /sbin/mdev ${KOPT_debug_init:+-d} \
${KOPT_usbdelay:+-t $(( $KOPT_usbdelay * 1000 ))} \
/dev/mapper/"$name"
eend $?
done

# We need to continue only if there is at least one cryptrootX specified
[ "$any" = "true" ] || exit 0

# Since btrfs needs all devices to be present, scanning cannot be done by the
# nlplug-findfs above. So lets do both lvm and btrfs manually here.
if [ -x /sbin/lvm ]; then
/sbin/lvm vgchange -aya --noudevsync --sysinit -qq
fi
if [ -x /sbin/btrfs ]; then
/sbin/btrfs device scan >/dev/null || \
echo "Failed to scan devices for btrfs filesystem."
fi
)

if [ -n "$KOPT_nbd" ]; then
# TODO: Might fail because nlplug-findfs hasn't plugged eth0 yet
configure_ip
Expand Down
28 changes: 28 additions & 0 deletions mkinitfs-bootparam.7.in
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,39 @@ security implications.
After the block device has been decrypted, make it available as
/dev/mapper/\fINAME\fR.
.TP
\fBcryptdm[0-9]=\fINAME\fR
After the block device has been decrypted, make it available as
/dev/mapper/\fINAME\fR. See "CRYPTO NOTES" for details.
.TP
\fBcryptheader=\fIDEVICE\fR
When the LUKS headers and encrypted data are on different devices, this option
specifies the device with the LUKS headers.
.TP
\fBcryptheader[0-9]=\fIDEVICE\fR
When the LUKS headers and encrypted data are on different devices, this option
specifies the device with the LUKS headers. See "CRYPTO NOTES" for details.
.TP
\fBcryptkey=\fIKEYFILE\fR
Attempt to decrypt an encypted partition using an keyfile.
.TP
\fBcryptkey[0-9]=\fIKEYFILE\fR
Attempt to decrypt an encypted partition using an keyfile. See "CRYPTO NOTES"
for details.
.TP
\fBcryptoffset=\fISECTORS\fR
Indicate that the encrypted data begins the given number of sectors after the
start of the block device.
.TP
\fBcryptoffset[0-9]=\fISECTORS\fR
Indicate that the encrypted data begins the given number of sectors after the
start of the block device. See "CRYPTO NOTES" for details.
.TP
\fBcryptroot=\fIDEVICE\fR
Attempt to decrypt \fIDEVICE\fR.
.TP
\fBcryptroot[0-9]=\fIDEVICE\fR
Attempt to decrypt \fIDEVICE\fR. See "CRYPTO NOTES" for details.
.TP
\fBdasd\fR
Enable DASD devices on S/390x architectures.
.TP
Expand Down Expand Up @@ -130,6 +149,15 @@ from a different system/OS.
.TP
\fI@datadir@/initramfs-init\fR
Default script that will be run in the initramfs.
.SH CRYPTO NOTES
There are two ways to specify what encrypted device should be unlocked.
.PP
One is \fBcryptroot=\fR family of options. 99% of the time this is what you want
to use. It works just fine as long as you need to unlock just one device.
.PP
Other is \fBcryptroot[0-9]=\fR family of options. When you have your root on
for example btrfs raid1, you need to unlock multiple devices. Up to 10 devices
can be specified.
.SH AUTHOR
.PP
Written by Natanael Copa <[email protected]>, Timo Teräs <[email protected]> and others.
Expand Down