-
Notifications
You must be signed in to change notification settings - Fork 56
/
yubikey-luks-open
103 lines (90 loc) · 2.91 KB
/
yubikey-luks-open
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/bin/sh
DISK="/dev/sda3"
NAME="yubikey-luks"
DBG=0
YUBIKEY_LUKS_SLOT=2 #Set this in case the value is missing in /etc/ykluks.cfg
set -e
. /etc/ykluks.cfg
while getopts ":d:n:hv" opt; do
case $opt in
d)
DISK=$OPTARG
echo "setting disk to $OPTARG."
;;
n)
NAME=$OPTARG
echo "setting name to $OPTARG."
;;
v)
DBG=1
echo "debugging enabled"
;;
h)
echo
echo " -d <partition>: select existing partition"
echo " -n <name> : set the new container name"
echo " -v : show input/output in cleartext"
echo
exit 1
;;
\?)
echo "Invalid option: -$OPTARG" >&2
;;
esac
done
echo "This script will try opening $NAME LUKS container on drive $DISK . If this is not what you intended, exit now!"
while true ; do
if lsusb | grep -iq 'yubico'; then break; fi
printf "Please insert a yubikey and press enter."
read -r _ <&1
done
P1=$(/lib/cryptsetup/askpass "Enter password created with yubikey-luks-enroll:")
if [ "$DBG" = "1" ]; then echo "Password: $P1"; fi
if [ "$HASH" = "1" ]; then
P1=$(printf %s "$P1" | sha256sum | awk '{print $1}')
if [ "$DBG" = "1" ]; then echo "Password hash: $P1"; fi
fi
R="$(printf %s "$P1" | ykchalresp -"$YUBIKEY_LUKS_SLOT" -i- 2>/dev/null || true)"
if [ "$DBG" = "1" ]; then echo "Yubikey response: $R"; fi
if [ -z "$R" ]; then
echo "Yubikey not available or timed out waiting for button press"
exit 1
fi
_passphrase=''
if [ "$CONCATENATE" = "1" ]; then
_passphrase=$(printf '%s' "$P1$R")
else
_passphrase=$(printf '%s' "$R")
fi
if [ "$DBG" = "1" ]; then echo "LUKS key: ${_passphrase}"; fi
if [ "$(id -u)" -eq 0 ]; then
printf %s "${_passphrase}" | cryptsetup luksOpen "$DISK" "$NAME" 2>&1;
else
# c-style escapes are not available in sh, so instead of doing symply
# $'\n' we have to put a newline in a variable, see:
# https://github.com/koalaman/shellcheck/wiki/SC2039
_n="$(printf '%b_' '\n')"
_n="${_n%_}"
# reading a HEREDOC to a variable in a POSIX-compliant shell, see:
# https://unix.stackexchange.com/a/340907/162158
# basically, the while loop reads the HEREDOC line-by-line (IFS set to
# newline) and concatenates everything in a variable and adds a newline.
expect_script=''
OLDIFS="$IFS"
while IFS="${_n}" read -r line; do
expect_script="$expect_script$line${_n}"
done <<EXPECTSCRIPT
set timeout -1;
spawn udisksctl unlock -b "$DISK";
match_max 100000;
expect -exact "Passphrase: ";
send -- "${_passphrase}\\r";
expect eof
EXPECTSCRIPT
# get rid of all tabs and convert newlines to spaces in the expect script,
# otherwise it will break when it is piped to expect
expect_script=$(echo "$expect_script" | tr -d '\t' | tr '\n' ' ')
IFS="$OLDIFS"
echo "$expect_script" | expect -f -
fi
exit 0