diff options
author | Fabian Beutel | 2015-08-24 14:11:07 +0200 |
---|---|---|
committer | Fabian Beutel | 2015-08-24 14:11:07 +0200 |
commit | 91bc48c29b6d933bf1a68f24d4293ba60d123c20 (patch) | |
tree | 0f7451272d4cdc1c020fa640d847f645795f91d5 | |
download | aur-mkinitcpio-smartcard.tar.gz |
Initial commit
-rw-r--r-- | .SRCINFO | 17 | ||||
-rw-r--r-- | PKGBUILD | 18 | ||||
-rw-r--r-- | smartcard_hook | 103 | ||||
-rw-r--r-- | smartcard_install | 74 |
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 +} |