]> git.pld-linux.org Git - projects/geninitrd.git/blob - mod-luks.sh
Handle deleted device files for swap.
[projects/geninitrd.git] / mod-luks.sh
1 #!/bin/sh
2 # geninitrd mod: cryptsetup luks
3 USE_LUKS=${USE_LUKS:-yes}
4
5 # true if root device is crypted with cryptsetup luks
6 # and we should init cryptsetup luks at boot
7 have_luks=no
8
9 # device to use for name for cryptsetup luks
10 LUKSNAME=""
11
12 # setup geninitrd module
13 # @access       public
14 setup_mod_luks() {
15         cryptsetup=$(find_tool $initrd_dir/cryptsetup /sbin/cryptsetup-initrd)
16
17         if [ ! -x /sbin/cryptsetup ] || [ ! -x "$cryptsetup" ]; then
18                 USE_LUKS=no
19         fi
20 }
21
22 # return true if node is cryptsetup luks encrypted
23 # @param        string $node device node to be examined
24 # @access       public
25 is_luks() {
26         local node="$1"
27
28         # luks not wanted
29         if is_no "$USE_LUKS"; then
30                 return 1
31         fi
32
33         local dev dm_name=${node#/dev/mapper/}
34         if [ "$node" = "$dm_name" ]; then
35                 verbose "is_luks: $node is not device mapper name"
36                 return 1
37         fi
38
39         dev=$(awk -vdm_name="$dm_name" '$1 == dm_name { print $2 }' /etc/crypttab)
40         if [ "$dev" ]; then
41                 dev=$(find_devname "$dev")
42                 /sbin/cryptsetup isLuks $dev
43                 rc=$?
44         else
45                 rc=1
46         fi
47
48         if [ $rc = 0 ]; then
49                 verbose "is_luks: $node is cryptsetup luks"
50         else
51                 verbose "is_luks: $node is not cryptsetup luks"
52         fi
53         return $rc
54 }
55
56 # find modules for $devpath
57 # @param        $devpath        device to be examined
58 # @access       public
59 find_modules_luks() {
60         local devpath="$1"
61         local dev=""
62
63         LUKSNAME=${devpath#/dev/mapper/}
64
65         find_module "dm-crypt"
66
67         # TODO: autodetect
68         find_module "-aes"
69         find_module "-cbc"
70         find_module "-cbc(aes)"
71         find_module "-xts(aes)"
72         find_module "-af-alg"
73         find_module "-algif_hash"
74         find_module "-algif_skcipher"
75         find_module "-loop"
76
77         # recurse
78         dev=$(awk -vLUKSNAME="$LUKSNAME" '$1 == LUKSNAME { print $2 }' /etc/crypttab)
79         if [ -n "$dev" ]; then
80                 dev=$(find_devname "$dev")
81                 find_modules_for_devpath $dev
82                 have_luks=yes
83         else
84                 die "Cannot find '$LUKSNAME' in /etc/crypttab"
85         fi
86 }
87
88
89 # generate initrd fragment for cryptsetup luks init
90 # @access       public
91 initrd_gen_luks() {
92         if ! is_yes "$have_luks"; then
93                 return
94         fi
95
96         inst_d /bin
97         inst_exec $cryptsetup /bin/cryptsetup
98         inst_d /var/run/cryptsetup
99
100         mount_dev
101         mount_sys
102         initrd_gen_devices
103         # TODO: 'udevadm settle' is called by lukssetup, is udev optional?
104
105         verbose "luks: process /etc/crypttab $LUKSNAME"
106         luks_crypttab $LUKSNAME
107 }
108
109
110 # PRIVATE METHODS
111 key_is_random() {
112         [ "$1" = "/dev/urandom" -o "$1" = "/dev/hw_random" -o "$1" = "/dev/random" ]
113 }
114
115 # produce cryptsetup from $name from /etc/crypttab
116 luks_crypttab() {
117         local LUKSNAME="$1"
118
119         # copy from /etc/rc.d/init.d/cryptsetup
120         local dst src key opt mode owner failsafe token libdir cryptdir
121
122         while read dst src key opt; do
123                 [ "$dst" != "$LUKSNAME" ] && continue
124
125                 failsafe=""
126
127                 if [ -z "$key" ] || [ "x$key" = "xnone" ] || [ "x$key" = "x-" ]; then
128                         failsafe=1
129                         key="/etc/cryptsetup-keys.d/$LUKSNAME.key"
130                 fi
131
132                 if test -e "$key" ; then
133                         mode=$(LC_ALL=C ls -l "$key" | cut -c 5-10)
134                         owner=$(LC_ALL=C ls -l $key | awk '{ print $3 }')
135                         if [ "$mode" != "------" ] && ! key_is_random "$key"; then
136                                 die "INSECURE MODE FOR $key"
137                         fi
138                         if [ "$owner" != root ]; then
139                                 die "INSECURE OWNER FOR $key"
140                         fi
141                 elif [ -n "$failsafe" ]; then
142                         key=""
143                 else
144                         die "Key file for $dst not found"
145                 fi
146
147                 src=$(find_devname "$src")
148                 if /sbin/cryptsetup isLuks "$src" 2>/dev/null; then
149                         if key_is_random "$key"; then
150                                 die "$dst: LUKS requires non-random key, skipping"
151                         fi
152                         if [ "$key" ]; then
153                                 keyfile=/etc/.$dst.key
154                                 inst $key $keyfile
155                         fi
156                         for libdir in $(get_libdir /usr/LIBDIR); do
157                                 if [ -d $libdir/cryptsetup ]; then
158                                         cryptdir=$libdir/cryptsetup
159                                         break
160                                 fi
161                         done
162                         if ! is_no "$USE_LUKS_TOKEN" && [ -n "$cryptdir" ]; then
163                                 for token in $(/sbin/cryptsetup luksDump $src | sed -n -e '/^Tokens:/,/^[^[:space:]]/ { /^[[:space:]]*[[:digit:]]*:/ { s/^[[:space:]]*[[:digit:]]*:[[:space:]]*// p } }'); do
164                                         verbose "Found cryptsetup token: $token"
165                                         case "$token" in
166                                                 systemd-fido2)
167                                                         inst_d $cryptdir
168                                                         inst_exec $cryptdir/libcryptsetup-token-$token.so $cryptdir
169                                                         inst_exec $libdir/libfido2.so.1 $libdir
170                                                         ;;
171                                                 systemd-tpm2)
172                                                         inst_d $cryptdir
173                                                         inst_exec $cryptdir/libcryptsetup-token-$token.so $cryptdir
174                                                         inst_exec $libdir/libtss2-esys.so.0 $libdir/libtss2-rc.so.0 $libdir/libtss2-mu.so.0 $libdir
175                                                         ;;
176                                                 *)
177                                                         inst_d $cryptdir
178                                                         inst_exec $cryptdir/libcryptsetup-token-$token.so $cryptdir
179                                                         ;;
180                                         esac
181                                 done
182                         fi
183
184                         crypttab_opt=""
185                         old_IFS="$IFS"
186                         IFS=","
187                         for option in $opt; do
188                                 case "$option" in
189                                         discard|allow-discards)
190                                                 crypttab_opt="$crypttab_opt --allow-discards"
191                                                 ;;
192                                         *)
193                                                 warn "$dst: option \'$option\' is unsupported for LUKS partitions, ignored"
194                                                 ;;
195                                 esac
196                         done
197                         IFS="$old_IFS"
198
199                         verbose "+ cryptsetup ${keyfile:+-d $keyfile} open $crypttab_opt '$src' '$dst'"
200                         add_linuxrc <<-EOF
201                         debugshell
202
203                         cryptsetup_opt=""
204                         if [ "\$DEBUGINITRD" ]; then
205                                 cryptsetup_opt="--debug"
206                         fi
207                         # cryptsetup can be called twice and in case on crypt on lvm only second
208                         # will succeed because there will be no src device in first cryptsetup call
209                         # this can be called multiple times, before lvm and after lvm.
210                         luksdev='$src'
211                         if [ \${luksdev##/dev/disk/by-uuid/} != \${luksdev} ]; then
212                                 src_uuid=\${luksdev##/dev/disk/by-uuid/}
213                                 while read x y z name; do
214                                         found_uuid=\$(cryptsetup \$cryptsetup_opt luksUUID /dev/\${name} 2>/dev/null)
215                                         if [ "\$found_uuid" = "\$src_uuid" ]; then
216                                                 luksdev=/dev/\$name
217                                                 break
218                                         fi
219                                 done < /proc/partitions
220                         fi
221
222                         if [ -e "\$luksdev" ]; then
223                                 crypt_status=\$(cryptsetup \$cryptsetup_opt status '$dst')
224                                 if [ "\${crypt_status%%is inactive*}" != "\$crypt_status" ]; then
225                                         # is inactive
226                                         cryptsetup \$cryptsetup_opt ${keyfile:+-d $keyfile} open $crypttab_opt "\$luksdev" '$dst' <&1
227                                 fi
228                         fi
229
230                         debugshell
231                         EOF
232                 else
233                         die "$dst: only LUKS encryption supported"
234                 fi
235         done < /etc/crypttab
236 }
This page took 0.127542 seconds and 4 git commands to generate.