@@ -28,87 +28,75 @@ 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- }
44+ # Gets the luks device to be unlocked and used pins
45+ get_pid_device_pins () {
46+ local pid=" $1 "
47+ local CRYPTTAB_SOURCE
5348
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
49+ CRYPTTAB_SOURCE=$( tr ' \0' ' \n' 2> /dev/null < /proc/${pid} /environ | \
50+ grep ' ^CRYPTTAB_SOURCE=' | cut -d= -f2)
6151
62- lml= $( luksmeta load -d " ${ CRYPTTAB_SOURCE} " -s " ${slot} " -u " ${UUID} " )
63- [ $? -eq 0 ] || continue
52+ # Wrong process, no CRYPTTAB_SOURCE, return error
53+ [ -n " $CRYPTTAB_SOURCE " ] || return 1
6454
65- decrypted=$( echo -n " ${lml} " | clevis decrypt 2> /dev/null)
66- [ $? -eq 0 ] || continue
55+ [ -b " $CRYPTTAB_SOURCE " ] || return 0
6756
68- # Fail safe
69- [ " $decrypted " != " " ] || continue
57+ local cache=" /var/cache/clevis-disks/${CRYPTTAB_SOURCE// \/ / _} "
58+ if [ ! -f " $cache " ]; then
59+ local pins=$( clevis_luks_used_pins " $CRYPTTAB_SOURCE " )
60+ echo " ${CRYPTTAB_SOURCE} :${pins} " > " $cache "
61+ fi
7062
71- echo -n " ${decrypted} " > " $PASSFIFO "
72- return 0
73- done
63+ cat " $cache "
64+ return 0
65+ }
7466
75- return 1
67+ # Print colon-separated password-asking info like device, pins and fifo
68+ # path for unlocking with password
69+ get_askpass_info () {
70+ local cryptkeyscript=$1
71+ local psinfo pf dev_pins
72+ psinfo=$( ps -A) # Doing this so I don't end up matching myself
73+ echo " $psinfo " | awk " /$cryptkeyscript / { print \$ 1 }" | {
74+ while read -r pid; do
75+ if pf=$( get_pid_fifo_path " ${pid} " ) && dev_pins=$( get_pid_device_pins " ${pid} " ) ; then
76+ if [[ $pf != " " && $dev_pins != " " ]]; then
77+ # Output only in case of clevis device
78+ echo " ${dev_pins} :${pf} "
79+ fi
80+ # Return that we found valid process
81+ return 0
82+ fi
83+ done
84+ return 1
85+ }
7686}
7787
78- luks2_decrypt () {
88+ # Try to decrypt the password to fifo file
89+ luks_decrypt () {
7990 local CRYPTTAB_SOURCE=$1
8091 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
92+ local pt
8593
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
94-
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 "
94+ if pt=$( clevis_luks_unlock_device " ${CRYPTTAB_SOURCE} " ) ; then
95+ echo -n " ${pt} " > " ${PASSFIFO} "
10296 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
97+ else
98+ return 1
99+ fi
112100}
113101
114102# Wait for askpass, and then try and decrypt immediately. Just in case
@@ -118,71 +106,69 @@ clevisloop() {
118106 # Set the path how we want it (Probably not all needed)
119107 PATH=" /sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin"
120108
109+ local cryptkeyscript
110+ local askpass_info
111+ local sleep_time
112+ local OLD_CRYPTTAB_SOURCE=" "
113+ local netcfg_attempted=0
114+ local tpm1cfg_attempted=0
115+
121116 if [ -x /bin/plymouth ] && plymouth --ping; then
122117 cryptkeyscript=' plymouth ask-for-password'
123118 else
124119 # This has to be escaped for awk
125120 cryptkeyscript=' \/lib\/cryptsetup\/askpass'
126121 fi
127122
128- OLD_CRYPTTAB_SOURCE=" "
129- local netcfg_attempted=0
130-
131123 while true ; do
132-
133124 # 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-)
125+ CRYPTTAB_SOURCE=" "
126+ sleep_time=.1
127+ until [ -n " $CRYPTTAB_SOURCE " ] && [ -p " $PASSFIFO " ]; do
128+ sleep $sleep_time
129+ if askpass_info=$( get_askpass_info " $cryptkeyscript " ) ; then
130+ # Workaround for initramfs-tools checking the script as sh-compatible
131+ IFS=' :' read -r CRYPTTAB_SOURCE pins PASSFIFO << EOM
132+ ${askpass_info}
133+ EOM
134+ # Ask process is running, variables might be empty for non-clevis device
135+ sleep_time=.5
136+ else
137+ # No valid process found
138+ sleep_time=.1
139+ fi
140140 done
141141
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
151142 # Make the source has changed if needed
152143 [ " $CRYPTTAB_SOURCE " = " $OLD_CRYPTTAB_SOURCE " ] && continue
153144 OLD_CRYPTTAB_SOURCE=" $CRYPTTAB_SOURCE "
154145
155- if [ $netcfg_attempted -eq 0 ] && has_tang_pin ${CRYPTTAB_SOURCE} ; then
146+ if [[ " $pins " == * " tang " * ]] && [ $netcfg_attempted -eq 0 ] ; then
156147 netcfg_attempted=1
157148 do_configure_networking
158149 fi
150+ if [[ " $pins " == * " tpm1 " * ]] && [ $tpm1cfg_attempted -eq 0 ]; then
151+ tpm1cfg_attempted=1
152+ do_configure_tpm1
153+ fi
159154
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
155+ if luks_decrypt " ${CRYPTTAB_SOURCE} " " ${PASSFIFO} " ; then
156+ echo " Unlocked ${CRYPTTAB_SOURCE} with clevis"
163157
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
158+ # Now that the current device has its password, let's sleep a
159+ # bit. This gives cryptsetup time to actually decrypt the
160+ # device and prompt for the next password if needed.
161+ sleep .5
162+ else
163+ # Unable to unlock now, retry later
164+ OLD_CRYPTTAB_SOURCE=" "
165+ sleep 5
177166 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
182167 done
183168}
184169
185170. /scripts/functions
171+ . clevis-luks-common-functions
186172
187173# This is a copy of 'all_netbootable_devices/all_non_enslaved_devices' for
188174# platforms that might not provide it.
@@ -229,9 +215,11 @@ get_specified_device() {
229215# to appear. This code can be removed once that has been fixed in all the
230216# distro releases we care about.
231217wait_for_device () {
232- local device= " $( get_specified_device ) "
218+ local device
233219 local ret=0
234220
221+ device=$( get_specified_device)
222+
235223 if [ -n " $device " ]; then
236224 log_begin_msg " clevis: Waiting for interface ${device} to become available"
237225 local netdev_wait=0
@@ -283,5 +271,32 @@ do_configure_networking() {
283271 fi
284272}
285273
274+ do_configure_tpm1 () {
275+ local tcsd_output=
276+
277+ [ -x @bindir@/clevis-decrypt-tpm1 ] && [ -f @libexecdir@/clevis-luks-tpm1-functions ] || return
278+
279+ . @libexecdir@/clevis-luks-tpm1-functions
280+
281+ log_begin_msg " clevis: Starting TCSD daemon"
282+
283+ wait_for_udev 10
284+
285+ if tcsd_output=$( start_tcsd 2>&1 ) ; then
286+ log_success_msg " clevis: TCSD up and running"
287+ else
288+ if [ -n " $tcsd_output " ]; then
289+ log_failure_msg " clevis: Unable to start TCSD: $tcsd_output "
290+ else
291+ log_failure_msg " clevis: Unable to start TCSD"
292+ fi
293+ fi
294+
295+ log_end_msg
296+ }
297+
298+ mkdir -p /var/cache/clevis-disks
299+ chmod 0700 /var/cache/clevis-disks
300+
286301clevisloop &
287302echo $! > /run/clevis.pid
0 commit comments