summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Beutel2015-08-24 14:11:07 +0200
committerFabian Beutel2015-08-24 14:11:07 +0200
commit91bc48c29b6d933bf1a68f24d4293ba60d123c20 (patch)
tree0f7451272d4cdc1c020fa640d847f645795f91d5
downloadaur-mkinitcpio-smartcard.tar.gz
Initial commit
-rw-r--r--.SRCINFO17
-rw-r--r--PKGBUILD18
-rw-r--r--smartcard_hook103
-rw-r--r--smartcard_install74
4 files changed, 212 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..443d37cb5c7a
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,17 @@
+pkgbase = mkinitcpio-smartcard
+ pkgdesc = mkinitcpio hook for two-factor authentication using a PGP smartcard and GnuPG
+ pkgver = 0.1.0
+ pkgrel = 1
+ url = https://bitbucket.org/fbeutel/mkinitcpio-smartcard
+ arch = any
+ license = GPL
+ depends = mkinitcpio>=0.9.0
+ depends = gnupg
+ depends = pcsclite
+ source = smartcard_hook
+ source = smartcard_install
+ md5sums = e871af7f97fdda1554bde59e99640818
+ md5sums = 438345555e5e9ac759c1f7270ed52aeb
+
+pkgname = mkinitcpio-smartcard
+
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..c2b287c1898b
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,18 @@
+# Contributor: Fabian Beutel <fabian.beutel at gmx dot de>
+pkgname='mkinitcpio-smartcard'
+pkgver=0.1.0
+pkgrel=1
+pkgdesc='mkinitcpio hook for two-factor authentication using a PGP smartcard and GnuPG'
+url='https://bitbucket.org/fbeutel/mkinitcpio-smartcard'
+arch=('any')
+license=('GPL')
+depends=('mkinitcpio>=0.9.0' 'gnupg' 'pcsclite')
+source=('smartcard_hook' 'smartcard_install')
+
+package() {
+ install -o root -g root -D ${srcdir}/smartcard_install ${pkgdir}/usr/lib/initcpio/install/smartcard
+ install -o root -g root -D ${srcdir}/smartcard_hook ${pkgdir}/usr/lib/initcpio/hooks/smartcard
+}
+
+md5sums=('e871af7f97fdda1554bde59e99640818'
+ '438345555e5e9ac759c1f7270ed52aeb')
diff --git a/smartcard_hook b/smartcard_hook
new file mode 100644
index 000000000000..d378a4a20ac7
--- /dev/null
+++ b/smartcard_hook
@@ -0,0 +1,103 @@
+#!/usr/bin/ash
+
+run_hook() {
+ [ "${quiet}" = "y" ] && CSQUIET=">/dev/null"
+
+ if [ -n "$gpgdir" ]; then
+ IFS=: read gpgdir_dev gpgdir_fs gpgdir_dirname <<EOF
+$gpgdir
+EOF
+
+ if [ -n "$cryptkey" ]; then
+ echo "Warning: The 'cryptkey' kernel parameter has also been provided."
+ echo "The 'cryptkey' parameter will be overwritten by the [smartcard] hook."
+ fi
+
+ ckeyfile="/crypto_keyfile.bin.gpg"
+ ckeyfile_out="/crypto_keyfile.bin"
+ dogpgdecryption=0
+
+
+ # Copy the GPG directory
+ if resolved=$(resolve_device "${gpgdir_dev}" ${rootdelay}); then
+
+ # Mount
+ mkdir /gpgdrive
+ mount -r -t "$gpgdir_fs" "$resolved" /gpgdrive
+
+ gpgdir_basepath="/gpgdrive/$gpgdir_dirname"
+ if [ -d "$gpgdir_basepath" ]; then
+
+ # Copy .gnupg homedirectory
+ if [ -d "$gpgdir_basepath/homedir" ]; then
+ mkdir -p "/.gnupg"
+ cp -a -r -T "$gpgdir_basepath/homedir/" "/.gnupg/"
+ fi
+
+ # Copy keyfile
+ if [ -f "$gpgdir_basepath/key.gpg" ]; then
+ dd if="$gpgdir_basepath/key.gpg" of="$ckeyfile" >/dev/null 2>&1
+ dogpgdecryption=1
+ else
+ echo "GPG directory found, but it contains no key.gpg"
+ fi
+
+ else
+ echo "Could not access GPG directory."
+ fi
+
+ umount /gpgdrive
+ fi
+
+ # Check for encrypted keyfile
+ [ ! -f ${ckeyfile} ] && echo "GPG-encrypted Keyfile could not be opened. Reverting to normal keyfile or passphrase." && dogpgdecryption=0
+
+
+ # Decrypt keyfile using GPG
+ if [ ${dogpgdecryption} -gt 0 ]; then
+
+ # Run PCSC daemon
+ pcscd &
+
+ # Limit the number of tries
+ maxtries=2
+ tries=0
+ success=0
+
+ while [ $maxtries -gt $tries ] && [ $success -ne 1 ]; do
+ tries=$((tries+1))
+
+ echo "Enter PIN or passphrase for GPG decryption:"
+ read -s pincode
+
+ # todo: run gpg --card-status
+ # That imports the private key stubs from the card.
+ # However, it doesn't create the public keys and thus the decryption will not work
+ # without public keys being available seperately.
+
+ if eval printf '%s' "$pincode" | gpg --batch --passphrase-fd 0 --pinentry-mode loopback --homedir "/.gnupg" --output ${ckeyfile_out} --decrypt ${ckeyfile} ${CSQUIET}; then
+
+ success=1
+ # Set cryptkey for encrypt hook
+ cryptkey="rootfs:${ckeyfile_out}:"
+ else
+ echo "GPG decryption failed! Wrong PIN? Smart card device inserted?"
+ fi
+ done
+
+
+ if [ $success -ne 1 ]; then
+ echo "Aborting GPG decryption!"
+ fi
+
+ # for now: kill gpg-agent and pcscd so that the smart card can be used by the normal user. In that case, the PIN has to be entered again.
+ # todo: maybe somehow pass the GPG agent session on to the user
+ killall gpg-agent
+ killall pcscd
+ fi
+
+
+ else
+ echo "No GPG-encrypted keyfile provided."
+ fi
+} \ No newline at end of file
diff --git a/smartcard_install b/smartcard_install
new file mode 100644
index 000000000000..466abbc1edf7
--- /dev/null
+++ b/smartcard_install
@@ -0,0 +1,74 @@
+#!/usr/bin/bash
+
+
+add_full_dir_resolve() {
+ # Add a directory and all its contents, recursively, to the initcpio image.
+ # adds symlink targets as well and adds binaries as binary
+
+ local f= filter=${2:-*}
+
+ if [[ -n $1 && -d $1 ]]; then
+ add_dir "$1"
+
+ for f in "$1"/*; do
+ if [[ -L $f ]]; then
+ if [[ $f = $filter ]]; then
+ add_symlink "$f" "$(readlink "$f")"
+ add_binary "$(readlink "$f")"
+ fi
+ elif [[ -d $f ]]; then
+ add_full_dir_resolve "$f"
+ elif [[ -f $f ]]; then
+ if [[ $f = $filter ]]; then
+ add_binary "$f"
+ fi
+ fi
+ done
+ fi
+}
+
+build() {
+
+ # GPG files
+ add_binary 'gpg'
+ add_binary 'gpg-agent'
+ add_binary 'gpgconf'
+ add_binary 'gpg-connect-agent'
+ add_binary 'applygnupgdefaults'
+ add_binary 'addgnupghome'
+ add_binary '/usr/lib/gnupg/scdaemon'
+
+ # PCSC files
+ add_binary 'pcscd'
+ add_binary '/usr/lib/libpcsclite.so'
+ add_binary '/usr/lib/libpcscspy.so'
+ add_binary '/usr/lib/libgcc_s.so'
+
+ add_full_dir_resolve '/usr/lib/pcsc'
+
+ # GPG Agent configuration
+ mkdir -p "$BUILDROOT/.gnupg"
+ printf '%s\n%s\n%s' 'allow-loopback-pinentry' 'default-cache-ttl 60' 'max-cache-ttl 60'>"$BUILDROOT/.gnupg/gpg-agent.conf"
+
+
+ add_runscript
+}
+
+help() {
+ cat <<HELPEOF
+This hook enables smartcard support in initramfs. It uses GPG 2 to decrypt a
+keyfile and use it as the keyfile for the 'encrypt' hook.
+
+The smartcard hook can be configured by the 'gpgdir=device:fstype:directory'
+kernel parameter, where directory is the path to a directory (without leading
+slash) containing a file named 'key.gpg' and a directory called 'homedir',
+whose contents will be used for the GPG home directory (there you can store
+the key database that links to the secret keys on the smart card, but
+obviously shouldn't contain any secret keys).
+
+The hook will decrypt the 'key.gpg' file and use it as key file for the [encrypt]
+hook.
+If the 'cryptkey' kernel parameter is also provided, it will be ignored and
+overwritten by the smartcard hook.
+HELPEOF
+}