cryptroot-ask.sh: use key file, if specified in crypttab and present
[platform/upstream/dracut.git] / modules.d / 90crypt / cryptroot-ask.sh
1 #!/bin/sh
2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
4
5 PATH=/usr/sbin:/usr/bin:/sbin:/bin
6 NEWROOT=${NEWROOT:-"/sysroot"}
7
8 # do not ask, if we already have root
9 [ -f $NEWROOT/proc ] && exit 0
10
11 # check if destination already exists
12 [ -b /dev/mapper/$2 ] && exit 0
13
14 # we already asked for this device
15 [ -f /tmp/cryptroot-asked-$2 ] && exit 0
16
17 # load dm_crypt if it is not already loaded
18 [ -d /sys/module/dm_crypt ] || modprobe dm_crypt
19
20 . /lib/dracut-crypt-lib.sh
21
22 # default luksname - luks-UUID
23 luksname=$2
24
25 # fallback to passphrase
26 ask_passphrase=1
27
28 # if device name is /dev/dm-X, convert to /dev/mapper/name
29 if [ "${1##/dev/dm-}" != "$1" ]; then
30     device="/dev/mapper/$(dmsetup info -c --noheadings -o name "$1")"
31 else
32     device="$1"
33 fi
34
35 # TODO: improve to support what cmdline does
36 if [ -f /etc/crypttab ] && getargbool 1 rd.luks.crypttab -n rd_NO_CRYPTTAB; then
37     while read name dev luksfile rest; do
38         # ignore blank lines and comments
39         if [ -z "$name" -o "${name#\#}" != "$name" ]; then
40             continue
41         fi
42
43         # UUID used in crypttab
44         if [ "${dev%%=*}" = "UUID" ]; then
45             if [ "luks-${dev##UUID=}" = "$2" ]; then
46                 luksname="$name"
47                 break
48             fi
49
50         # path used in crypttab
51         else
52             cdev=$(readlink -f $dev)
53             mdev=$(readlink -f $device)
54             if [ "$cdev" = "$mdev" ]; then
55                 luksname="$name"
56                 break
57             fi
58         fi
59     done < /etc/crypttab
60     unset name dev rest
61 fi
62
63 #
64 # Open LUKS device
65 #
66
67 info "luksOpen $device $luksname $luksfile"
68
69 if [ -n "$luksfile" -a "$luksfile" != "none" -a -e "$luksfile" ]; then
70     if cryptsetup --key-file "$luksfile" luksOpen "$device" "$luksname"; then
71         ask_passphrase=0
72     fi
73 else
74     while [ -n "$(getarg rd.luks.key)" ]; do
75         if tmp=$(getkey /tmp/luks.keys $device); then
76             keydev="${tmp%%:*}"
77             keypath="${tmp#*:}"
78         else
79             if [ $# -eq 3 ]; then
80                 if [ $3 -eq 0 ]; then
81                     info "No key found for $device.  Fallback to passphrase mode."
82                     break
83                 fi
84                 info "No key found for $device.  Will try $3 time(s) more later."
85                 set -- "$1" "$2" "$(($3 - 1))"
86             else
87                 info "No key found for $device.  Will try later."
88             fi
89             initqueue --unique --onetime --settled \
90                 --name cryptroot-ask-$luksname \
91                 $(command -v cryptroot-ask) "$@"
92             exit 0
93         fi
94         unset tmp
95
96         info "Using '$keypath' on '$keydev'"
97         readkey "$keypath" "$keydev" "$device" \
98             | cryptsetup -d - luksOpen "$device" "$luksname"
99         unset keypath keydev
100         ask_passphrase=0
101         break
102     done
103 fi
104
105 if [ $ask_passphrase -ne 0 ]; then
106     luks_open="$(command -v cryptsetup) luksOpen"
107     ask_for_password --ply-tries 5 \
108         --ply-cmd "$luks_open -T1 $device $luksname" \
109         --ply-prompt "Password ($device)" \
110         --tty-tries 1 \
111         --tty-cmd "$luks_open -T5 $device $luksname"
112     unset luks_open
113 fi
114
115 unset device luksname luksfile
116
117 # mark device as asked
118 >> /tmp/cryptroot-asked-$2
119
120 udevsettle
121
122 exit 0