104

This question is related to another one by @Stefan, but it is not a duplicate of it. The questions are slightly different: the author simply wanted to know if this had been implemented, while I'm asking for help specifically on how to do this (in a particular way). Additionally, the other question got no useful answers for implementers, except a recent one that merely linked to my attempt at this.

Having explained the "duplicate" issue...

I'm on Ubuntu 14.04 using full disk encryption (LVM on top of LUKS) and I would like to incorporate luksSuspend into the suspend procedure (and later use luksResume) so that I can suspend to RAM without leaving key material on memory and the root unlocked.

I've tried to port a script for Arch Linux, so far without success: I honestly have no idea of what I'm doing...

Can anyone help me port this (or create something like this from scratch)? Or, at least, can anyone point me to documentation about how to hook stuff into the suspend procedures and how to keep the necessary binaries and scripts (such as cryptsetup) available even after all IO to root has been blocked (by luksSuspend)?

Concerning how to keep the necessary binaries and scripts available for resume, this other blog post (also for Arch) copied them to /boot; I would like however to use something more in the lines what Vianney used in the script I mentioned before, because that approach appears to be a bit more elegant in this aspect.

I haven't reached much, but my development can be found on GitHub.

Jonas Malaco
  • 1,453
  • 1
  • 13
  • 15
  • have you tried adding manual lock command to hibernate/resume actions ? for example adding udisksctl lock -b /dev/sda to a script in /etc/pm/sleep.d/ directory? – AliReza Mosajjal Aug 09 '15 at 07:08
  • Thanks, I'll look into it... From what I can already tell, this is more general than the LUKS only cryptsetup luksSuspend I've been using, but on the other hand requires unmounting the filesystem. Also, it probably wont work in a jail (since it communicates with the udisksd daemon) and couldn't be used to remount/resume the filesystem. – Jonas Malaco Aug 10 '15 at 19:57
  • Even if removing the key material there is probably other confidential information in memory during suspend to RAM. So what's point in getting only rid of the luks key? – pefu Jan 28 '16 at 09:47
  • @pefu Well, first, the amount of confidential info on disk can be much larger than that left in RAM. Additionally, the attacker capability to identify and/or change info on RAM is rather limited when compared to having access to the decrypted filesystem. – Jonas Malaco Jan 28 '16 at 10:23
  • @jonasmalacofilho: Well: I consider my private keys as the most confidential material in my laptop. Of course these private keys are also protected by a passphrase. On startup I usually load these keys and have a agent running which of course has a decrypted copy of these keys stored somewhere in RAM. So if my computer falls into the hands of a sophisticated attacker who is able to bypass any screen saver security and salvage the data from RAM I would be screwed even if I had destroyed the LUKS key in RAM before going into suspend. Right? – pefu Jan 29 '16 at 09:17
  • @pefu, yes, you would (specially since crypto material seems easy to spot in RAM). However, one can have multiple keys (and only a few of loaded in RAM at any given time), use short a very caching timout, or even set up his agents to unload all keys before suspending... – Jonas Malaco Jan 29 '16 at 12:35

2 Answers2

1

Sorry to state the obvious, but have you tried adding a script containing the cryptsetup luksSuspend/luksResume commands to the /usr/lib/pm-utils/sleep.d? If so what happened?

It would seem logical to me, to call stop/start the cryptdisks and cryptdisks_early services on hibernate/resume too. Would calling cryptdisks_stop and cryptdisks_start within a script in pm-utils/sleep.d do the trick? I assume this would have the same result as calling cryptsetup luksSuspend directly.

qbi
  • 19,125
sibaz
  • 793
  • 1
  • 7
  • 20
  • So far my approach was to change pm-suspend. However, there still appears to be some kernel modules loaded that require access to the root fs when trying to suspend (with echo mem > /sys/power/state). See the linked repository for more details. – Jonas Malaco Sep 18 '15 at 13:36
0

The closest solution I've been able to find is this 2013 proof of concept suspend.sh script by Mikko Rauhala.

#!/bin/sh

# A proof of concept script for forgetting LUKS passwords on suspend
# and reasking them on resume.

# The basic idea is to copy all of the files necessary for luksResume
# onto a RAM disk so that we can be sure they'll be available without
# touching the disk at all. Then switch to a text VT to run the resume
# (easier to make sure it'll come up than to do the same with X).

# The suspend itself has to be done from the ramdisk too to make sure it
# won't hang. This is also a reason why this couldn't be reliably done as a
# self-contained /etc/pm/sleep.d script, so to make the concept clear
# (and because I'm lazy) I did just a minimal standalone proof of concept
# instead. Integrating the functionality into the usual pm tools would be
# encouraged. (Though suspend_pmu would apparently need perl on the ramdisk...)

# (C) 2013 Mikko Rauhala 2013, modifiable and distributable under
# CC0, GPLv2 or later, MIT X11 license or 2-clause BSD. Regardless
# of what you pick, there is NO WARRANTY of any kind.

RAMDEV=/dev/ram0
ROOT=/run/cryptosuspend

PATH=/sbin:/bin:/usr/sbin:/usr/bin

# Cleanup not strictly necessary every time but good for development.
# Doing it before rather than after a suspend for debugging purposes

for a in "$ROOT"/dev/pts "$ROOT"/proc "$ROOT"/sys "$ROOT" ; do
    umount "$a" > /dev/null 2>&1
done

if mount | grep -q "$ROOT" ; then
    echo "Cleanup unsuccessful, cryptosuspend root premounted." 1>&2
    exit 2
fi

if grep -q mem /sys/power/state; then
    METHOD=mem
elif grep -q standby /sys/power/state; then
    METHOD=standby
else
    echo "No mem or standby states available, aborting" 1>&2
    exit 1
fi

if ! mount | grep -q "$RAMDEV" ; then
    mkfs -t ext2 -q "$RAMDEV" 8192
    mkdir -p "$ROOT"
    mount "$RAMDEV" "$ROOT"
    mkdir "$ROOT"/sbin "$ROOT"/bin "$ROOT"/dev "$ROOT"/tmp "$ROOT"/proc "$ROOT"/sys
    cp "$(which cryptsetup)" "$ROOT"/sbin
    for a in $(ldd "$(which cryptsetup)" | grep "/" | cut -d / -f 2- | cut -d " " -f 1) ; do
        mkdir -p "$ROOT""$(dirname /$a)"
        cp "/$a" "$ROOT"/"$a"
    done
    cp "$(which busybox)" "$ROOT"/bin/
    ln -s busybox "$ROOT"/bin/sh
    ln -s busybox "$ROOT"/bin/sync
    cp -a /dev "$ROOT"
    mount -t proc proc "$ROOT"/proc
    mount -t sysfs sysfs "$ROOT"/sys
    mount -t devpts devpts "$ROOT"/dev/pts
fi

CRYPTDEVS="$(dmsetup --target crypt status | cut -d : -f 1)"

echo '#!/bin/sh' > "$ROOT"/bin/cryptosuspend
echo "sync" >> "$ROOT"/bin/cryptosuspend
echo "for a in $CRYPTDEVS ; do" >> "$ROOT"/bin/cryptosuspend
echo "  cryptsetup luksSuspend \$a" >> "$ROOT"/bin/cryptosuspend
echo "done" >> "$ROOT"/bin/cryptosuspend
echo "echo -n \"$METHOD\" > /sys/power/state" >> "$ROOT"/bin/cryptosuspend
echo "for a in $CRYPTDEVS ; do" >> "$ROOT"/bin/cryptosuspend
echo '  while ! cryptsetup luksResume'" \$a ; do" >> "$ROOT"/bin/cryptosuspend
echo "    true" >> "$ROOT"/bin/cryptosuspend
echo "  done" >> "$ROOT"/bin/cryptosuspend
echo "done" >> "$ROOT"/bin/cryptosuspend
chmod a+rx "$ROOT"/bin/cryptosuspend

sync
exec openvt -s chroot "$ROOT" /bin/cryptosuspend

Some work has been done towards porting this to Ubuntu 14.04 here. This is by no means a perfect solution as there are still some open issues and it appears that no work has been released since Jun 11, 2014. However it seems a good starting point for future development.

Source:https://github.com/jonasmalacofilho/ubuntu-luks-suspend

Elder Geek
  • 36,023
  • 25
  • 98
  • 183