add PARTLABEL and PARTUUID
[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 # number of tries
36 numtries=${3:-10}
37
38 # TODO: improve to support what cmdline does
39 if [ -f /etc/crypttab ] && getargbool 1 rd.luks.crypttab -d -n rd_NO_CRYPTTAB; then
40     while read name dev luksfile luksoptions; do
41         # ignore blank lines and comments
42         if [ -z "$name" -o "${name#\#}" != "$name" ]; then
43             continue
44         fi
45
46         # UUID used in crypttab
47         if [ "${dev%%=*}" = "UUID" ]; then
48             if [ "luks-${dev##UUID=}" = "$2" ]; then
49                 luksname="$name"
50                 break
51             fi
52
53         # path used in crypttab
54         else
55             cdev=$(readlink -f $dev)
56             mdev=$(readlink -f $device)
57             if [ "$cdev" = "$mdev" ]; then
58                 luksname="$name"
59                 break
60             fi
61         fi
62     done < /etc/crypttab
63     unset name dev
64 fi
65
66 #
67 # Open LUKS device
68 #
69
70 info "luksOpen $device $luksname $luksfile $luksoptions"
71
72 OLD_IFS="$IFS"
73 IFS=,
74 set -- $luksoptions
75 IFS="$OLD_IFS"
76
77 while [ $# -gt 0 ]; do
78     case $1 in
79         noauto)
80             # skip this
81             exit 0
82             ;;
83         swap)
84             # skip this
85             exit 0
86             ;;
87         tmp)
88             # skip this
89             exit 0
90             ;;
91         allow-discards)
92             allowdiscards="--allow-discards"
93     esac
94     shift
95 done
96
97 # parse for allow-discards
98 if strstr "$(cryptsetup --help)" "allow-discards"; then
99     if discarduuids=$(getargs "rd.luks.allow-discards"); then
100         discarduuids=$(str_replace "$discarduuids" 'luks-' '')
101         if strstr " $discarduuids " " ${luksdev##luks-}"; then
102             allowdiscards="--allow-discards"
103         fi
104     elif getargbool 0 rd.luks.allow-discards; then
105         allowdiscards="--allow-discards"
106     fi
107 fi
108
109 if strstr "$(cryptsetup --help)" "allow-discards"; then
110     cryptsetupopts="$cryptsetupopts $allowdiscards"
111 fi
112
113 unset allowdiscards
114
115 if [ -n "$luksfile" -a "$luksfile" != "none" -a -e "$luksfile" ]; then
116     if cryptsetup --key-file "$luksfile" $cryptsetupopts luksOpen "$device" "$luksname"; then
117         ask_passphrase=0
118     fi
119 else
120     while [ -n "$(getarg rd.luks.key)" ]; do
121         if tmp=$(getkey /tmp/luks.keys $device); then
122             keydev="${tmp%%:*}"
123             keypath="${tmp#*:}"
124         else
125             if [ $numtries -eq 0 ]; then
126                 warn "No key found for $device.  Fallback to passphrase mode."
127                 break
128             fi
129             sleep 1
130             info "No key found for $device.  Will try $numtries time(s) more later."
131             initqueue --unique --onetime --settled \
132                 --name cryptroot-ask-$luksname \
133                 $(command -v cryptroot-ask) "$device" "$luksname" "$(($numtries-1))"
134             exit 0
135         fi
136         unset tmp
137
138         info "Using '$keypath' on '$keydev'"
139         readkey "$keypath" "$keydev" "$device" \
140             | cryptsetup -d - $cryptsetupopts luksOpen "$device" "$luksname"
141         unset keypath keydev
142         ask_passphrase=0
143         break
144     done
145 fi
146
147 if [ $ask_passphrase -ne 0 ]; then
148     luks_open="$(command -v cryptsetup) $cryptsetupopts luksOpen"
149     ask_for_password --ply-tries 5 \
150         --ply-cmd "$luks_open -T1 $device $luksname" \
151         --ply-prompt "Password ($device)" \
152         --tty-tries 1 \
153         --tty-cmd "$luks_open -T5 $device $luksname"
154     unset luks_open
155 fi
156
157 unset device luksname luksfile
158
159 # mark device as asked
160 >> /tmp/cryptroot-asked-$2
161
162 need_shutdown
163 udevsettle
164
165 exit 0