diff options
author | mwberry | 2016-10-22 20:34:30 +0000 |
---|---|---|
committer | mwberry | 2016-10-23 18:36:36 +0000 |
commit | 31c2985fd0f88cc7b1edf89b40208a46fe2c5c8c (patch) | |
tree | 74b3134179bb55bf8e3b028edf030241eca9e91d | |
download | aur-mkinitcpio-yk2fe.tar.gz |
Two-Factor Full Disk Encrytion with Yubikey Challenge-Response
mkinitcpio hook and associated scripts to enable two factor
disk encryption. A passphrase serves as the first factor and
is used as the challenge for the Yubikey's challenge-response
protocol. The unextractable secret in the Yubikey serves as the
second factor.
-rw-r--r-- | .SRCINFO | 22 | ||||
-rw-r--r-- | PKGBUILD | 34 | ||||
-rwxr-xr-x | add_yk2fe | 70 | ||||
-rwxr-xr-x | hook | 5 | ||||
-rwxr-xr-x | install | 36 | ||||
-rwxr-xr-x | yk2fe | 37 |
6 files changed, 204 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..215142998084 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,22 @@ +pkgbase = mkinitcpio-yk2fe + pkgdesc = Two factor LUKS disk encryption using Yubikey Challenge Response + pkgver = 0.1 + pkgrel = 1 + url = https://wiki.archlinux.org/index.php/User:Mwberry/mkinitcpio-ykchalresp + arch = any + license = GPL2 + depends = cryptsetup-keyscript + depends = yubikey-personalization + depends = bash + depends = coreutils + source = hook + source = install + source = yk2fe + source = add_yk2fe + md5sums = a25aea71328a2df06424c39526d6e58b + md5sums = f771e7efc28075811c6c0115cbd21bc3 + md5sums = 63cb9137d5e76a51177fffc4f2806458 + md5sums = 43f2ac34098f5dc44f266fc8b844b692 + +pkgname = mkinitcpio-yk2fe + diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..d51bf81ad44e --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,34 @@ +# Maintainer: mwberry <null [at] example [dot] org> +pkgname=mkinitcpio-yk2fe +pkgver=0.1 +pkgrel=1 +pkgdesc="Two factor LUKS disk encryption using Yubikey Challenge Response" +url="https://wiki.archlinux.org/index.php/User:Mwberry/mkinitcpio-ykchalresp" +arch=('any') +license=('GPL2') +depends=('cryptsetup-keyscript' 'yubikey-personalization' 'bash' 'coreutils') +optdepends=() +makedepends=() +conflicts=() +replaces=() +backup=() +install='' +source=('hook' 'install' 'yk2fe' 'add_yk2fe') +md5sums=( + '70415485bc618f06c04b17ee6dff6e5f' + 'dca02e52b6241822e490b5465992bec6' + '63cb9137d5e76a51177fffc4f2806458' + '43f2ac34098f5dc44f266fc8b844b692' +) + +# No build step because all sources are shell scripts + +package() { + + install -D "${srcdir}/yk2fe" "${pkgdir}/usr/lib/yk2fe/yk2fe" + install -D "${srcdir}/add_yk2fe" "${pkgdir}/usr/bin/add_yk2fe" + install -D "${srcdir}/hook" "${pkgdir}/usr/lib/initcpio/hooks/yk2fe" + install -D "${srcdir}/install" "${pkgdir}/usr/lib/initcpio/install/yk2fe" +} + +# vim:set ts=2 sw=2 et: diff --git a/add_yk2fe b/add_yk2fe new file mode 100755 index 000000000000..7335cdeb9142 --- /dev/null +++ b/add_yk2fe @@ -0,0 +1,70 @@ +#!/bin/bash + +set -e +set -u + +usage () { + cat <<EOF +# ================== +# Prior to running this script to add a Yubikey as a LUKS passphrase, first +# configure your Yubikey for challenge-response with the following: +# +# ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 [-ochal-btn-trig] +# +# Refer to the manpage for ykpersonalize for details on each option. +# -ochal-btn-trig is optional but strongly recommended so that you +# are always aware of when your Yubikey performs an HMAC. It can, however +# cause problems if you are attempting to use the same slot as a means of +# logging into a local Windows account (which may or may not matter for you). +# +# Expected Usage: +# +# add_2fa [-1 | -2] | cryptsetup addLuksKey /device +# +# The first argument is optional and names the Yubikey slot to use for the +# challenge-response protocol. Default is "-2". This script will correspond +# with cryptsetup's addLuksKey dialog to add the Yubikey's response as a +# disk encryption passphrase. Although this can be achived via a keyfile, +# passing the response via stdout means the response (which is in effect +# the same as a passphrase in sensitivity) never hits the disk and therefore +# never needs to be shredded. +EOF +} + +DEFAULT_SLOT="-2" +SLOT="${1:-$DEFAULT_SLOT}" +if ! ( [[ "$SLOT" == "-1" ]] || [[ "$SLOT" == "-2" ]] ) ; then + usage >&2 + exit 1 +fi + +echo "Enter an existing LUKS passphrase: " >&2 +read -s existing +echo "Enter a new first factor passphrase: " >&2 +read -s first + +response='' +until [[ "$response" != "" ]]; do + # A little side note about ykchalresp. Originally there was + # more comprehensive error handling here, but it was ugly + # because ykchalresp uses 1 for just about every failure + # mode. The stderr was different, but capturing both stdout + # and stderr is a real challenge in shell and relying on + # error messages is a bad idea (tm) anyway. So now stderr + # bubbles out to the user and this script loops until the + # user gives up. + echo "Use your Yubikey as a second factor: " >&2 + if stdout=$(ykchalresp "$SLOT" "$first") ; then + response="$stdout" + else + echo "Press enter before trying again" >&2 + read -s enter + fi +done + +echo "Adding key to Luks container" >&2 + +# The following is based on the 'cryptsetup luksAddKey' dialog +echo "$existing" +echo "$response" +echo "$response" @@ -0,0 +1,5 @@ +#!/bin/sh + +# The main scipt of this hook is not directly invoked by the +# init script, but rather an associated script is invoked by +# the encrypt hook via the cryptkeyscript argument. diff --git a/install b/install new file mode 100755 index 000000000000..b0f7ea967cee --- /dev/null +++ b/install @@ -0,0 +1,36 @@ +#!/bin/bash + +build() { + + add_binary "ykchalresp" + + add_file "/usr/lib/yk2fe/yk2fe" + add_file "/usr/bin/add_yk2fe" + add_file "/usr/lib/udev/rules.d/69-yubikey.rules" +} + +help() { + cat <<HELPEOF +This hook collects a two-factor encryption passphrase using a Yubikey configured +for challenge-response as the second factor. This hook is intended to be used in +conjunction with the 'encrypt' hook with the 'cryptkeyscript' argument on the +kernel command line pointing to '/usr/lib/yk2fe/yk2fe'. + +cryptdevice=UUID=c87dcfc0-14a5-4afe-b4e9-bd81f952149c:encrypt-root +cryptkeyscript=rootfs::/usr/lib/yk2fe/yk2fe + +The encrypt hook will invoke the cryptkeyscript, which will block on user input. +The script will prompt for a first factor passphrase. After that is entered, the +script will use the first factor passphrase as a challenge to an attached +Yubikey. The response of which will be passed to cryptsetup via the encrypt +hook. + +This hook assumes slot 2 of the Yubikey is configured for challenge-response, if +slot 1 is configured for challenge-response, enter -1 as the first factor +passphrase. The script will then use slot 1 and will re-prompt for the first- +factor passphrase. + +HELPEOF +} + +# vim: set ft=sh ts=4 sw=4 et: diff --git a/yk2fe b/yk2fe new file mode 100755 index 000000000000..851a6fdb0c8e --- /dev/null +++ b/yk2fe @@ -0,0 +1,37 @@ +#!/bin/sh + +set -u +set -e + +SLOT="-2" + +echo "Enter first factor passphrase (enter -1 to use slot one): " >&2 +read -s first + +if [[ "$first" == "-1" ]]; then + SLOT="-1" + echo "Using slot 1. Enter first factor passphrase: " >&2 + read -s first +fi + +response='' +until [[ "$response" != "" ]]; do + # A little side note about ykchalresp. Originally there was + # more comprehensive error handling here, but it was ugly + # because ykchalresp uses 1 for just about every failure + # mode. The stderr was different, but capturing both stdout + # and stderr is a real challenge in shell and relying on + # error messages is a bad idea (tm) anyway. So now stderr + # bubbles out to the user and this script loops until the + # user gives up. + echo "Use your Yubikey as a second factor: " >&2 + if stdout=$(ykchalresp "$SLOT" "$first") ; then + response="$stdout" + else + echo "Press enter before trying again" >&2 + read -s enter + fi +done + +echo "$response" + |