@@ -49,6 +49,7 @@ pub(crate) enum BlockSetup {
4949 #[ default]
5050 Direct ,
5151 Tpm2Luks ,
52+ PasswordLuks ,
5253}
5354
5455impl Display for BlockSetup {
@@ -73,9 +74,14 @@ pub(crate) struct InstallBlockDeviceOpts {
7374 ///
7475 /// direct: Filesystem written directly to block device
7576 /// tpm2-luks: Bind unlock of filesystem to presence of the default tpm2 device.
77+ /// password-luks: Encrypt filesystem with LUKS using a password.
7678 #[ clap( long, value_enum) ]
7779 pub ( crate ) block_setup : Option < BlockSetup > ,
7880
81+ /// Password for LUKS encryption when `block_setup` is `password-luks`.
82+ #[ clap( long) ]
83+ pub ( crate ) luks_password : Option < String > ,
84+
7985 /// Target root filesystem type.
8086 #[ clap( long, value_enum) ]
8187 pub ( crate ) filesystem : Option < Filesystem > ,
@@ -93,6 +99,7 @@ impl BlockSetup {
9399 match self {
94100 BlockSetup :: Direct => false ,
95101 BlockSetup :: Tpm2Luks => true ,
102+ BlockSetup :: PasswordLuks => true ,
96103 }
97104 }
98105}
@@ -222,6 +229,13 @@ pub(crate) fn install_create_rootfs(
222229 // and we need to error out.
223230 anyhow:: bail!( "No install configuration found, and no filesystem specified" )
224231 } ;
232+
233+ // Validate luks_password if PasswordLuks is selected
234+ if block_setup == BlockSetup :: PasswordLuks && opts. luks_password . is_none ( ) {
235+ anyhow:: bail!( "--luks-password is required when block-setup is password-luks" ) ;
236+ }
237+
238+
225239 let serial = device. serial . as_deref ( ) . unwrap_or ( "<unknown>" ) ;
226240 let model = device. model . as_deref ( ) . unwrap_or ( "<unknown>" ) ;
227241 println ! ( "Block setup: {block_setup}" ) ;
@@ -367,6 +381,27 @@ pub(crate) fn install_create_rootfs(
367381 ] ;
368382 ( rootdev, Some ( kargs) )
369383 }
384+ BlockSetup :: PasswordLuks => {
385+ let uuid = uuid:: Uuid :: new_v4 ( ) . to_string ( ) ;
386+ let password = opts. luks_password . as_ref ( ) . unwrap ( ) ;
387+ let root_devpath = root_partition. path ( ) ;
388+
389+ Task :: new ( "Initializing LUKS for root" , "cryptsetup" )
390+ . args ( [ "--verbose" , "--batch" , "luksFormat" , "--uuid" , uuid. as_str ( ) ] )
391+ . args ( [ root_devpath] )
392+ . run_with_stdin_buf ( Some ( password. as_bytes ( ) ) ) ?;
393+ Task :: new ( "Opening root LUKS device" , "cryptsetup" )
394+ . args ( [ "luksOpen" , root_devpath. as_str ( ) , luks_name] )
395+ . run_with_stdin_buf ( Some ( password. as_bytes ( ) ) ) ?;
396+
397+ let rootdev = format ! ( "/dev/mapper/{luks_name}" ) ;
398+ // Kernel arguments for password-based LUKS
399+ // rd.luks.uuid is preferred for systemd initramfs
400+ let kargs = vec ! [
401+ format!( "luks.uuid={uuid}" ) ,
402+ ] ;
403+ ( rootdev, Some ( kargs) )
404+ }
370405 } ;
371406
372407 // Initialize the /boot filesystem
@@ -448,6 +483,7 @@ pub(crate) fn install_create_rootfs(
448483 let luks_device = match block_setup {
449484 BlockSetup :: Direct => None ,
450485 BlockSetup :: Tpm2Luks => Some ( luks_name. to_string ( ) ) ,
486+ BlockSetup :: PasswordLuks => Some ( luks_name. to_string ( ) ) ,
451487 } ;
452488 let device_info = bootc_blockdev:: partitions_of ( & devpath) ?;
453489 Ok ( RootSetup {
0 commit comments