@@ -28,87 +28,73 @@ prereqs) exit 0 ;;
2828esac
2929
3030# Return fifo path or nothing if not found
31- get_fifo_path () {
31+ get_pid_fifo_path () {
3232 local pid=" $1 "
3333 for fd in /proc/$pid /fd/* ; do
3434 if [ -e " $fd " ]; then
3535 if [[ $( readlink -f " ${fd} " ) == * " /cryptsetup/passfifo" ]]; then
3636 readlink -f " ${fd} "
37+ return 0
3738 fi
3839 fi
3940 done
41+ return 1
4042}
4143
42- # Print the PID of the askpass process and fifo path with a file descriptor opened to
43- get_askpass_pid () {
44- psinfo=$( ps) # Doing this so I don't end up matching myself
45- echo " $psinfo " | awk " /$cryptkeyscript / { print \$ 1 }" | while read -r pid; do
46- pf=$( get_fifo_path " ${pid} " )
47- if [[ $pf != " " ]]; then
48- echo " ${pid} ${pf} "
49- break
50- fi
51- done
52- }
53-
54- luks1_decrypt () {
55- local CRYPTTAB_SOURCE=$1
56- local PASSFIFO=$2
57- UUID=cb6e8904-81ff-40da-a84a-07ab9ab5715e
58- luksmeta show -d " $CRYPTTAB_SOURCE " | while read -r slot state uuid; do
59- [ " $state " == " active" ] || continue
60- [ " $uuid " == " $UUID " ] || continue
44+ # Gets the luks device to be unlocked and used pins
45+ get_pid_device_pins () {
46+ local pid=" $1 "
47+ local CRYPTTAB_SOURCE=$( cat /proc/${pid} /environ 2> /dev/null | \
48+ tr ' \0' ' \n' | grep ' ^CRYPTTAB_SOURCE=' | cut -d= -f2)
6149
62- lml= $( luksmeta load -d " ${ CRYPTTAB_SOURCE} " -s " ${slot} " -u " ${UUID} " )
63- [ $? -eq 0 ] || continue
50+ # Wrong process, no CRYPTTAB_SOURCE, return error
51+ [ -n " $CRYPTTAB_SOURCE " ] || return 1
6452
65- decrypted=$( echo -n " ${lml} " | clevis decrypt 2> /dev/null)
66- [ $? -eq 0 ] || continue
53+ [ -b " $CRYPTTAB_SOURCE " ] || return 0
6754
68- # Fail safe
69- [ " $decrypted " != " " ] || continue
55+ local cache=" /var/cache/clevis-disks/${CRYPTTAB_SOURCE// \/ / _} "
56+ if [ ! -f " $cache " ]; then
57+ local pins=$( clevis_luks_used_pins " $CRYPTTAB_SOURCE " )
58+ echo " ${CRYPTTAB_SOURCE} :${pins} " > " $cache "
59+ fi
7060
71- echo -n " ${decrypted} " > " $PASSFIFO "
72- return 0
73- done
61+ cat " $cache "
62+ return 0
63+ }
7464
75- return 1
65+ # Print colon-separated password-asking info like device, pins and fifo
66+ # path for unlocking with password
67+ get_askpass_info () {
68+ local cryptkeyscript=$1
69+ local psinfo pf dev_pins
70+ psinfo=$( ps -A) # Doing this so I don't end up matching myself
71+ echo " $psinfo " | awk " /$cryptkeyscript / { print \$ 1 }" | {
72+ while read -r pid; do
73+ if pf=$( get_pid_fifo_path " ${pid} " ) && dev_pins=$( get_pid_device_pins " ${pid} " ) ; then
74+ if [[ $pf != " " && $dev_pins != " " ]]; then
75+ # Output only in case of clevis device
76+ echo " ${dev_pins} :${pf} "
77+ fi
78+ # Return that we found valid process
79+ return 0
80+ fi
81+ done
82+ return 1
83+ }
7684}
7785
78- luks2_decrypt () {
86+ # Try to decrypt the password to fifo file
87+ luks_decrypt () {
7988 local CRYPTTAB_SOURCE=$1
8089 local PASSFIFO=$2
81- cryptsetup luksDump " $CRYPTTAB_SOURCE " | sed -rn ' s|^\s+([0-9]+): clevis|\1|p' | while read -r id; do
82- # jose jwe fmt -c outputs extra \n, so clean it up
83- cte=$( cryptsetup token export --token-id " $id " " $CRYPTTAB_SOURCE " )
84- [ $? -eq 0 ] || continue
85-
86- josefmt=$( echo " ${cte} " | jose fmt -j- -Og jwe -o-)
87- [ $? -eq 0 ] || continue
88-
89- josejwe=$( echo " ${josefmt} " | jose jwe fmt -i- -c)
90- [ $? -eq 0 ] || continue
91-
92- jwe=$( echo " ${josejwe} " | tr -d ' \n' )
93- [ $? -eq 0 ] || continue
90+ local pt
9491
95- decrypted=$( echo -n " ${jwe} " | clevis decrypt 2> /dev/null)
96- [ $? -eq 0 ] || continue
97-
98- # Fail safe
99- [ " $decrypted " != " " ] || continue
100-
101- echo -n " ${decrypted} " > " $PASSFIFO "
92+ if pt=$( clevis_luks_unlock_device " ${CRYPTTAB_SOURCE} " ) ; then
93+ echo -n " ${pt} " > " ${PASSFIFO} "
10294 return 0
103- done
104-
105- return 1
106- }
107-
108- has_tang_pin () {
109- local dev=" $1 "
110-
111- clevis luks list -d " ${dev} " | grep -q tang
95+ else
96+ return 1
97+ fi
11298}
11399
114100# Wait for askpass, and then try and decrypt immediately. Just in case
@@ -118,71 +104,69 @@ clevisloop() {
118104 # Set the path how we want it (Probably not all needed)
119105 PATH=" /sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin"
120106
107+ local cryptkeyscript
108+ local askpass_info
109+ local sleep_time
110+ local OLD_CRYPTTAB_SOURCE=" "
111+ local netcfg_attempted=0
112+ local tpm1cfg_attempted=0
113+
121114 if [ -x /bin/plymouth ] && plymouth --ping; then
122115 cryptkeyscript=' plymouth ask-for-password'
123116 else
124117 # This has to be escaped for awk
125118 cryptkeyscript=' \/lib\/cryptsetup\/askpass'
126119 fi
127120
128- OLD_CRYPTTAB_SOURCE=" "
129- local netcfg_attempted=0
130-
131121 while true ; do
132-
133122 # Re-get the askpass PID in case there are multiple encrypted devices
134- pid=" "
135- until [ " $pid " ] && [ -p " $PASSFIFO " ]; do
136- sleep .1
137- pid_fifo=$( get_askpass_pid)
138- pid=$( echo " ${pid_fifo} " | cut -d' ' -f1)
139- PASSFIFO=$( echo " ${pid_fifo} " | cut -d' ' -f2-)
123+ CRYPTTAB_SOURCE=" "
124+ sleep_time=.1
125+ until [ -n " $CRYPTTAB_SOURCE " ] && [ -p " $PASSFIFO " ]; do
126+ sleep $sleep_time
127+ if askpass_info=$( get_askpass_info " $cryptkeyscript " ) ; then
128+ # Workaround for initramfs-tools checking the script as sh-compatible
129+ IFS=' :' read -r CRYPTTAB_SOURCE pins PASSFIFO << EOM
130+ ${askpass_info}
131+ EOM
132+ # Ask process is running, variables might be empty for non-clevis device
133+ sleep_time=.5
134+ else
135+ # No valid process found
136+ sleep_time=.1
137+ fi
140138 done
141139
142- # Import CRYPTTAB_SOURCE from the askpass process.
143- local CRYPTTAB_SOURCE=" $( cat /proc/${pid} /environ 2> /dev/null | \
144- tr ' \0' ' \n' | grep ' ^CRYPTTAB_SOURCE=' | cut -d= -f2) "
145- [ -n " $CRYPTTAB_SOURCE " ] || continue
146-
147- # Make sure that CRYPTTAB_SOURCE is actually a block device
148- [ ! -b " $CRYPTTAB_SOURCE " ] && continue
149-
150- sleep .1
151140 # Make the source has changed if needed
152141 [ " $CRYPTTAB_SOURCE " = " $OLD_CRYPTTAB_SOURCE " ] && continue
153142 OLD_CRYPTTAB_SOURCE=" $CRYPTTAB_SOURCE "
154143
155- if [ $netcfg_attempted -eq 0 ] && has_tang_pin ${CRYPTTAB_SOURCE} ; then
144+ if [[ " $pins " == * " tang " * ]] && [ $netcfg_attempted -eq 0 ] ; then
156145 netcfg_attempted=1
157146 do_configure_networking
158147 fi
148+ if [[ " $pins " == * " tpm1 " * ]] && [ $tpm1cfg_attempted -eq 0 ]; then
149+ tpm1cfg_attempted=1
150+ do_configure_tpm1
151+ fi
159152
160- if cryptsetup isLuks --type luks1 " $CRYPTTAB_SOURCE " ; then
161- # If the device is not initialized, sliently skip it.
162- luksmeta test -d " $CRYPTTAB_SOURCE " || continue
153+ if luks_decrypt " ${CRYPTTAB_SOURCE} " " ${PASSFIFO} " ; then
154+ echo " Unlocked ${CRYPTTAB_SOURCE} with clevis"
163155
164- if luks1_decrypt " ${CRYPTTAB_SOURCE} " " ${PASSFIFO} " ; then
165- echo " Unlocked ${CRYPTTAB_SOURCE} with clevis"
166- else
167- OLD_CRYPTTAB_SOURCE=" "
168- sleep 5
169- fi
170- elif cryptsetup isLuks --type luks2 " $CRYPTTAB_SOURCE " ; then
171- if luks2_decrypt " ${CRYPTTAB_SOURCE} " " ${PASSFIFO} " ; then
172- echo " Unlocked ${CRYPTTAB_SOURCE} with clevis"
173- else
174- OLD_CRYPTTAB_SOURCE=" "
175- sleep 5
176- fi
156+ # Now that the current device has its password, let's sleep a
157+ # bit. This gives cryptsetup time to actually decrypt the
158+ # device and prompt for the next password if needed.
159+ sleep .5
160+ else
161+ # Unable to unlock now, retry later
162+ OLD_CRYPTTAB_SOURCE=" "
163+ sleep 5
177164 fi
178- # Now that the current device has its password, let's sleep a
179- # bit. This gives cryptsetup time to actually decrypt the
180- # device and prompt for the next password if needed.
181- sleep .5
182165 done
183166}
184167
185168. /scripts/functions
169+ . clevis-luks-common-functions
186170
187171# This is a copy of 'all_netbootable_devices/all_non_enslaved_devices' for
188172# platforms that might not provide it.
@@ -283,5 +267,33 @@ do_configure_networking() {
283267 fi
284268}
285269
270+ do_configure_tpm1 () {
271+ local tcsd_output=
272+ local tcsd_result
273+
274+ [ -x @bindir@/clevis-decrypt-tpm1 ] && [ -f @libexecdir@/clevis-luks-tpm1-functions ] || return
275+
276+ . @libexecdir@/clevis-luks-tpm1-functions
277+
278+ log_begin_msg " clevis: Starting TCSD daemon"
279+
280+ wait_for_udev 10
281+
282+ if tcsd_output=$( start_tcsd 2>&1 ) ; then
283+ log_success_msg " clevis: TCSD up and running"
284+ else
285+ if [ -n " $tcsd_output " ]; then
286+ log_failure_msg " clevis: Unable to start TCSD: $tcsd_output "
287+ else
288+ log_failure_msg " clevis: Unable to start TCSD"
289+ fi
290+ fi
291+
292+ log_end_msg
293+ }
294+
295+ mkdir -p -m 0755 /var/cache
296+ mkdir -p -m 0700 /var/cache/clevis-disks
297+
286298clevisloop &
287299echo $! > /run/clevis.pid
0 commit comments