summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authormwberry2016-10-22 20:34:30 +0000
committermwberry2016-10-23 18:36:36 +0000
commit31c2985fd0f88cc7b1edf89b40208a46fe2c5c8c (patch)
tree74b3134179bb55bf8e3b028edf030241eca9e91d
downloadaur-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--.SRCINFO22
-rw-r--r--PKGBUILD34
-rwxr-xr-xadd_yk2fe70
-rwxr-xr-xhook5
-rwxr-xr-xinstall36
-rwxr-xr-xyk2fe37
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"
diff --git a/hook b/hook
new file mode 100755
index 000000000000..5bfe93c12f3c
--- /dev/null
+++ b/hook
@@ -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"
+