11__author__ = 'desultory'
2- __version__ = '2.9 .0'
2+ __version__ = '3.2 .0'
33
44from zenlib .util import contains
55
66from pathlib import Path
77
88_module_name = 'ugrd.crypto.cryptsetup'
99
10- CRYPTSETUP_PARAMETERS = ['key_type' , 'partuuid' , 'uuid' , 'path' ,
11- 'key_file' , 'header_file' , 'retries' ,
12- 'key_command' , 'reset_command' , 'try_nokey' ,
13- 'include_key' , 'validate_key' , 'validate' ]
10+
11+ CRYPTSETUP_KEY_PARAMETERS = ['key_command' , 'plymouth_key_command' , 'reset_command' ]
12+ CRYPTSETUP_PARAMETERS = ['key_type' , 'partuuid' , 'uuid' , 'path' , 'key_file' , 'header_file' , 'retries' ,
13+ * CRYPTSETUP_KEY_PARAMETERS , 'try_nokey' , 'include_key' , 'validate_key' ]
14+
1415
1516
1617def _merge_cryptsetup (self , mapped_name : str , config : dict ) -> None :
@@ -30,7 +31,7 @@ def _process_cryptsetup_key_types_multi(self, key_type: str, config: dict) -> No
3031 """
3132 self .logger .debug ("[%s] Processing cryptsetup key type configuration: %s" % (key_type , config ))
3233 for parameter in config :
33- if parameter not in CRYPTSETUP_PARAMETERS :
34+ if parameter not in CRYPTSETUP_KEY_PARAMETERS :
3435 raise ValueError ("Invalid parameter: %s" % parameter )
3536
3637 # Update the key if it already exists, otherwise create a new key type
@@ -115,7 +116,7 @@ def _process_cryptsetup_multi(self, mapped_name: str, config: dict) -> None:
115116 config ['key_type' ] = key_type
116117
117118 # Inherit from the key type configuration
118- for parameter in [ 'key_command' , 'reset_command' ] :
119+ for parameter in CRYPTSETUP_KEY_PARAMETERS :
119120 if value := self ['cryptsetup_key_types' ][key_type ].get (parameter ):
120121 config [parameter ] = value .format (** config )
121122
@@ -282,51 +283,58 @@ def open_crypt_device(self, name: str, parameters: dict) -> list[str]:
282283 out = [f"prompt_user 'Press enter to unlock device: { name } '" ] if self ['cryptsetup_prompt' ] else []
283284 out += [f"for ((i = 1; i <= { retries } ; i++)); do" ]
284285
285- # When there is a key command, read from the named pipe and use that as the key
286+ # Resolve the device source using get_crypt_dev, if no source is returned, run rd_fail
287+ out += [f' crypt_dev="$(get_crypt_dev { name } )"' ,
288+ ' if [ -z "$crypt_dev" ]; then' ,
289+ f' rd_fail "Failed to resolve device source for cryptsetup mount: { name } "' ,
290+ ' fi' ]
291+
292+ # When there is a key command, evaluate it into $key_data
286293 if 'key_command' in parameters :
287294 self .logger .debug ("[%s] Using key command: %s" % (name , parameters ['key_command' ]))
288295 out += [f" einfo 'Attempting to open LUKS key: { parameters ['key_file' ]} '" ,
289- f" edebug 'Using key command: { parameters ['key_command' ]} '" ]
290- cryptsetup_command = f'{ parameters ["key_command" ]} | cryptsetup open --key-file -'
291- elif 'key_file' in parameters :
292- self .logger .debug ("[%s] Using key file: %s" % (name , parameters ['key_file' ]))
293- cryptsetup_command = f'cryptsetup open --key-file { parameters ["key_file" ]} '
294- else :
295- # Set tries to 1 since it runs in the loop
296- cryptsetup_command = 'cryptsetup open --tries 1'
296+ f" edebug 'Using key command: { parameters ['key_command' ]} '" ,
297+ ' if check_var plymouth; then' ,
298+ f' plymouth ask-for-password --prompt "[${{i}} / { retries } ] Enter passphrase to unlock key for: { name } " --command "{ parameters ["plymouth_key_command" ]} " --number-of-tries 1 > /run/vars/key_data || continue' ,
299+ ' else' ,
300+ f' { parameters ["key_command" ]} > /run/vars/key_data || continue' ,
301+ ' fi' ]
297302
298- # Add the header file if it exists
299- if header_file := parameters .get ('header_file' ):
303+ cryptsetup_command = 'cryptsetup open --tries 1' # Set tries to 1 since it runs in the loop
304+ cryptsetup_target = f'"$crypt_dev" { name } ' # Add a variable for the source device and mapped name
305+
306+ if header_file := parameters .get ('header_file' ): # Use the header file if it exists
300307 out += [f" einfo 'Using header file: { header_file } '" ]
301308 cryptsetup_command += f' --header { header_file } '
302309
303310 if self ['cryptsetup_trim' ]:
304311 cryptsetup_command += ' --allow-discards'
305312 self .logger .warning ("Using --allow-discards can be a security risk." )
306313
307- # Resolve the device source using get_crypt_dev, if no source is returned, run rd_fail
308- out += [f'crypt_dev="$(get_crypt_dev { name } )"' ,
309- 'if [ -z "$crypt_dev" ]; then' ,
310- f' rd_fail "Failed to resolve device source for cryptsetup mount: { name } "' ,
311- 'fi' ]
312-
313- # Add the variable for the source device and mapped name
314- cryptsetup_command += f' "$crypt_dev" { name } '
315-
316314 # Check if the device was successfully opened
317- out += [f' if { cryptsetup_command } ; then' ,
318- f' einfo "Successfully opened device: { name } "' ,
319- ' break' ,
320- ' else' ,
321- f' ewarn "Failed to open device: { name } ($i / { retries } )"' ]
315+ out += [' einfo "Unlocking device: $crypt_dev"' , # Unlock using key data if it exists
316+ ' if [ -e /run/vars/key_data ]; then' ,
317+ f' if { cryptsetup_command } --key-file=/run/vars/key_data { cryptsetup_target } ; then' ,
318+ ' rm /run/vars/key_data' , # Remove the key data file
319+ ' break' ,
320+ ' fi' , # Try to open the device using plymouth if it's running
321+ ' rm /run/vars/key_data' , # Remove the key data file
322+ f' elif check_var plymouth && plymouth ask-for-password --prompt "[${{i}} / { retries } ] Enter passphrase to unlock { name } " --command "{ cryptsetup_command } { cryptsetup_target } " --number-of-tries 1; then' ,
323+ ' break' ] # Break if the device was successfully opened
324+ if 'key_file' in parameters : # try a key file directly if it exists
325+ out += [f' elif { cryptsetup_command } --key-file { parameters ["key_file" ]} { cryptsetup_target } ; then' ]
326+ else : # Otherwise, open directly
327+ out += [f' elif { cryptsetup_command } { cryptsetup_target } ; then' ]
328+ out += [' break' ,
329+ ' fi' ,
330+ f' ewarn "Failed to open device: { name } ($i / { retries } )"' ]
322331 # Halt if the autoretry is disabled
323332 if not self ['cryptsetup_autoretry' ]:
324- out += [' prompt_user "Press enter to retry"' ]
333+ out += [' prompt_user "Press enter to retry"' ]
325334 # Add the reset command if it exists
326335 if reset_command := parameters .get ('reset_command' ):
327- out += [' einfo "Running key reset command"' ,
328- f' { reset_command } ' ]
329- out += [' fi' ]
336+ out += [' einfo "Running key reset command"' ,
337+ f' { reset_command } ' ]
330338 out += ['done\n ' ]
331339
332340 return out
0 commit comments