diff options
author | Corey Hinshaw | 2017-02-27 22:59:23 -0500 |
---|---|---|
committer | Corey Hinshaw | 2017-02-27 22:59:23 -0500 |
commit | 13e93ce1baef3a12a6cea6451d68c15796d09c2e (patch) | |
tree | bb2f6e51ca069dba3ed05a9f07d9a27d2678a8d8 | |
download | aur-13e93ce1baef3a12a6cea6451d68c15796d09c2e.tar.gz |
Initial commit
-rw-r--r-- | .SRCINFO | 17 | ||||
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | PKGBUILD | 17 | ||||
-rw-r--r-- | README.md | 57 | ||||
-rwxr-xr-x | luks-tpm | 197 |
5 files changed, 291 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..267ddb85232a --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,17 @@ +pkgbase = luks-tpm + pkgdesc = Utility to manage LUKS keyfiles sealed by the TPM + pkgver = 0.1.0 + pkgrel = 1 + url = https://github.com/electrickite/luks-tpm + arch = any + license = GPL + depends = tpm-tools + depends = trousers + depends = cryptsetup + depends = coreutils + depends = util-linux + source = luks-tpm + sha256sums = 97c7b2a7f45674e96ec25bd69f48bda7749c59bbf6744608d561f84410634198 + +pkgname = luks-tpm + diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..2b2f66f1ee18 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pkg.tar.xz +/pkg +/src diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..5086f28928c0 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,17 @@ +# Maintainer: Corey Hinshaw <coreyhinshaw@gmail.com> + +pkgname=luks-tpm +pkgver=0.1.0 +pkgrel=1 +pkgdesc="Utility to manage LUKS keyfiles sealed by the TPM" +arch=('any') +url="https://github.com/electrickite/luks-tpm" +license=('GPL') +depends=('tpm-tools' 'trousers' 'cryptsetup' 'coreutils' 'util-linux') +source=('luks-tpm') + +sha256sums=('97c7b2a7f45674e96ec25bd69f48bda7749c59bbf6744608d561f84410634198') + +package() { + install -Dm755 luks-tpm "${pkgdir}/usr/bin/luks-tpm" +} diff --git a/README.md b/README.md new file mode 100644 index 000000000000..8a7e4ad47e4e --- /dev/null +++ b/README.md @@ -0,0 +1,57 @@ +LUKS TPM +======== + +A small utility script to manage LUKS keyfiles sealed by a TPM. + +This script assumes you will be using a TPM-sealed keyfile during boot to unlock +the root file system. It is intended to be used as part of your kernel update +process to generate a keyfile sealed against the new kernel's PCR values. + +Update Process +-------------- + +The script facilitates te following kernel update process: + + 1. Kernel is updated + 2. `luks-tpm` is called, either manually or via pacman hook, and sets a + temporary LUKS passphrase + 3. The system is rebooted into the new kernel + 4. Because the TPM PCRs have changed, the old keyfile cannot be unsealed + 5. User enters the temporary passphrase to unlock the disk + 6. `luks-tpm` is called, generating a new keyfile sealed by the TPM and + removing the temporary passphrase + +###LUKS Key Slots + +The script requires two LUKS key slots to function: one for the sealed keyfile +and one for the temporary passphrase. You are also *strongly* encouraged to +dedicate an additional slot for a recovery passphrase not managed by `luks-tpm`. + +The default key slot layout is: + + * Slot 0: Recovery passphrase (optional) + * Slot 1: TPM keyfile + * Slot 2: Temporary passphrase + +Usage +----- + + luks-tpm [OPTION]... DEVICE ACTION + +###Actions + * `temp`: Set a temporary LUKS passphrase + * `reset`: Regenerate the LUKS TPM key and remove the temporary passphrase + +###Options + -h Print help + -m PATH Mount point for the tmpfs file system used to store TPM keyfiles + Default: /root/keyfs + -k PATH Sealed TPM keyfile path + Default: /boot/keyfile.enc + -t NUMBER LUKS slot number for the TPM keyfile + Default: 1 + -r NUMBER LUKS slot number for temporary reset passphrase + Default: 2 + -p NUMBER PCRs used to seal LUKS keyfile. May be specified more than once + Default: 0-7 + -z Use the TPM SRK well-known password diff --git a/luks-tpm b/luks-tpm new file mode 100755 index 000000000000..fac80d80e9e3 --- /dev/null +++ b/luks-tpm @@ -0,0 +1,197 @@ +#!/bin/bash + +# Copyright 2017 Corey Hinshaw <coreyhinshaw@gmail.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +usage () { + cat <<EOF +Usage: luks-tpm [OPTION]... DEVICE ACTION +Manage the LUKS TPM keys on DEVICE + +Actions: + temp Set a temporary LUKS passphrase + reset Reset the LUKS TPM key + +Options: + -h Print this help text + -m PATH Mount point for the tmpfs file system used to store TPM keyfiles + Default: /root/keyfs + -k PATH Sealed TPM keyfile path + Default: /boot/keyfile.enc + -t NUMBER LUKS slot number for the TPM keyfile + Default: 1 + -r NUMBER LUKS slot number for temporary reset passphrase + Default: 2 + -p NUMBER PCRs used to seal LUKS keyfile. May be specified more than once + Default: 0-7 + -z Use the TPM SRK well-known password +EOF +} + +add_temp_key() { + return_code=0 + create_tmpfs + tpm_unsealdata -i "$SEALED_KEYFILE" -o "$KEYFILE" $WELL_KNOWN + + echo "Preparing to set a temporary LUKS passphrase..." + cryptsetup luksAddKey --key-slot $RESET_KEY_SLOT --key-file "$KEYFILE" $ROOT_DEVICE < /dev/tty + + if [ $? -eq 0 ]; then + echo "After booting into the current kernel, run" + echo " luks-tpm $(echo $ORIGINAL_ARGS | sed 's/temp$/reset/')" + echo "to generate a new TPM keyfile and remove this temporary key" + else + echo "A temporary passphrase was not set" >&2 + return_code=5 + fi + + destroy_tmpfs + exit $return_code +} + +reset_tpm_key() { + return_code=0 + read -s -p "Enter any existing LUKS passphrase: " PASSPHRASE + echo + + echo "Generating new LUKS key..." + create_tmpfs + dd bs=512 count=4 if=/dev/urandom of="$KEYFILE" > /dev/null 2>&1 + + echo "Removing current TPM key from slot $TPM_KEY_SLOT..." + echo $PASSPHRASE | cryptsetup luksKillSlot $ROOT_DEVICE $TPM_KEY_SLOT + + echo "Adding new key to slot $TPM_KEY_SLOT..." + echo $PASSPHRASE | cryptsetup luksAddKey $ROOT_DEVICE "$KEYFILE" --key-slot $TPM_KEY_SLOT + addkey=$? + + echo "Sealing keyfile with the TPM..." + tpm_sealdata $PCRS -i "$KEYFILE" -o "$SEALED_KEYFILE" $WELL_KNOWN + seal=$? + + if [ $addkey -eq 0 ] && [ $seal -eq 0 ]; then + echo "Removing temporary passphrase from slot $RESET_KEY_SLOT..." + cryptsetup luksKillSlot --key-file "$KEYFILE" $ROOT_DEVICE $RESET_KEY_SLOT + else + echo "There was an error resetting the TPM key in slot $TPM_KEY_SLOT!" >&2 + echo "The temporary reset ket in slot $RESET_KEY_SLOT has not been removed." >&2 + return_code=4 + fi + + destroy_tmpfs + exit $return_code +} + +create_tmpfs() { + mkdir -p "$TMPFS_MOUNT" + mount tmpfs "$TMPFS_MOUNT" -t tmpfs -o size=1m + if [ $? -ne 0 ]; then + echo "Could not create tmpfs. Aborting..." >&2 + exit 3 + fi + chmod 700 "$TMPFS_MOUNT" +} + +destroy_tmpfs() { + umount "$TMPFS_MOUNT" +} + +ORIGINAL_ARGS="$@" +TMPFS_MOUNT=/root/keyfs +SEALED_KEYFILE=/boot/keyfile.enc +TPM_KEY_SLOT=1 +RESET_KEY_SLOT=2 +PCRS="-p 0 -p 1 -p 2 -p 3 -p 4 -p 5 -p 6 -p 7" +WELL_KNOWN="" + +while getopts ":hm:k:t:r:p:z" opt; do + case $opt in + h) + usage + exit 0 + ;; + m) + TMPFS_MOUNT="$OPTARG" + ;; + k) + SEALED_KEYFILE="$OPTARG" + ;; + t) + if [[ ! $OPTARG =~ ^-?[0-9]+$ ]] || [ $OPTARG -lt 0 ] || [ $OPTARG -gt 7 ]; then + echo "Invalid TPM key slot: $OPTARG" >&2 + exit 1 + fi + TPM_KEY_SLOT=$OPTARG + ;; + r) + if [[ ! $OPTARG =~ ^-?[0-9]+$ ]] || [ $OPTARG -lt 0 ] || [ $OPTARG -gt 7 ]; then + echo "Invalid reset key slot: $OPTARG" >&2 + exit 1 + fi + RESET_KEY_SLOT=$OPTARG + ;; + p) + if [[ ! $OPTARG =~ ^-?[0-9]+$ ]] || [ $OPTARG -lt 0 ] || [ $OPTARG -gt 23 ]; then + echo "Invalid PCR: $OPTARG" >&2 + exit 1 + fi + + if [ -z $pcr_option ]; then + PCRS="-p $OPTARG" + else + PCRS="$PCRS -p $OPTARG" + fi + pcr_option=1 + ;; + z) + WELL_KNOWN="-z" + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + usage >2& + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +shift $((OPTIND-1)) + +ROOT_DEVICE="$1" +KEYFILE="$TMPFS_MOUNT/keyfile" + +if [ -z $ROOT_DEVICE ]; then + echo "Device not specified!" >&2 + usage >&2 + exit 1 +fi + +if [ $EUID -ne 0 ]; then + echo "Must be run as root" >&2 + exit 2 +fi + +if [ "$2" = "temp" ]; then + add_temp_key +elif [ "$2" = "reset" ]; then + reset_tpm_key +else + echo "Invalid action!" >&2 + usage >&2 + exit 1 +fi |