7
7
8
8
use std:: borrow:: Cow ;
9
9
use std:: fmt:: Display ;
10
+ use std:: io:: Write ;
10
11
use std:: process:: Command ;
11
12
use std:: process:: Stdio ;
12
13
@@ -154,6 +155,7 @@ pub(crate) fn install_create_rootfs(
154
155
state : & State ,
155
156
opts : InstallBlockDeviceOpts ,
156
157
) -> Result < RootSetup > {
158
+ let luks_name = "root" ;
157
159
// Verify that the target is empty (if not already wiped in particular, but it's
158
160
// also good to verify that the wipe worked)
159
161
let device = crate :: blockdev:: list_dev ( & opts. device ) ?;
@@ -284,11 +286,41 @@ pub(crate) fn install_create_rootfs(
284
286
285
287
crate :: blockdev:: udev_settle ( ) ?;
286
288
287
- match opts. block_setup {
288
- BlockSetup :: Direct => { }
289
- // TODO
290
- BlockSetup :: Tpm2Luks => anyhow:: bail!( "tpm2-luks is not implemented yet" ) ,
291
- }
289
+ let base_rootdev = format ! ( "{device}{ROOTPN}" ) ;
290
+ let ( rootdev, root_blockdev_kargs) = match opts. block_setup {
291
+ BlockSetup :: Direct => ( base_rootdev, None ) ,
292
+ BlockSetup :: Tpm2Luks => {
293
+ let uuid = uuid:: Uuid :: new_v4 ( ) . to_string ( ) ;
294
+ // This will be replaced via --wipe-slot=all when binding to tpm below
295
+ let dummy_passphrase = uuid:: Uuid :: new_v4 ( ) . to_string ( ) ;
296
+ let mut tmp_keyfile = tempfile:: NamedTempFile :: new ( ) ?;
297
+ tmp_keyfile. write_all ( dummy_passphrase. as_bytes ( ) ) ?;
298
+ tmp_keyfile. flush ( ) ?;
299
+ let tmp_keyfile = tmp_keyfile. path ( ) ;
300
+ let dummy_passphrase_input = Some ( dummy_passphrase. as_bytes ( ) ) ;
301
+
302
+ Task :: new ( "Initializing LUKS for root" , "cryptsetup" )
303
+ . args ( [ "luksFormat" , "--uuid" , uuid. as_str ( ) , "--key-file" ] )
304
+ . args ( [ tmp_keyfile] )
305
+ . args ( [ base_rootdev. as_str ( ) ] )
306
+ . run ( ) ?;
307
+ // The --wipe-slot=all removes our temporary passphrase, and binds to the local TPM device.
308
+ Task :: new ( "Enrolling root device with TPM" , "systemd-cryptenroll" )
309
+ . args ( [ "--wipe-slot=all" , "--tpm2-device=auto" , "--unlock-key-file" ] )
310
+ . args ( [ tmp_keyfile] )
311
+ . args ( [ base_rootdev. as_str ( ) ] )
312
+ . run_with_stdin_buf ( dummy_passphrase_input) ?;
313
+ Task :: new ( "Opening root LUKS device" , "cryptsetup" )
314
+ . args ( [ "luksOpen" , base_rootdev. as_str ( ) , luks_name] )
315
+ . run ( ) ?;
316
+ let rootdev = format ! ( "/dev/mapper/{luks_name}" ) ;
317
+ let kargs = vec ! [
318
+ format!( "luks.uuid={uuid}" ) ,
319
+ format!( "luks.options=tpm2-device=auto,headless=true" ) ,
320
+ ] ;
321
+ ( rootdev, Some ( kargs) )
322
+ }
323
+ } ;
292
324
293
325
// TODO: make this configurable
294
326
let bootfs_type = Filesystem :: Ext4 ;
@@ -298,19 +330,22 @@ pub(crate) fn install_create_rootfs(
298
330
let boot_uuid = mkfs ( bootdev, bootfs_type, Some ( "boot" ) , [ ] ) . context ( "Initializing /boot" ) ?;
299
331
300
332
// Initialize rootfs
301
- let rootdev = & format ! ( "{device}{ROOTPN}" ) ;
302
333
let root_filesystem = opts
303
334
. filesystem
304
335
. or ( state. install_config . root_fs_type )
305
336
. ok_or_else ( || anyhow:: anyhow!( "No root filesystem specified" ) ) ?;
306
- let root_uuid = mkfs ( rootdev, root_filesystem, Some ( "root" ) , [ ] ) ?;
337
+ let root_uuid = mkfs ( & rootdev, root_filesystem, Some ( "root" ) , [ ] ) ?;
307
338
let rootarg = format ! ( "root=UUID={root_uuid}" ) ;
308
339
let bootsrc = format ! ( "UUID={boot_uuid}" ) ;
309
340
let bootarg = format ! ( "boot={bootsrc}" ) ;
310
341
let boot = MountSpec :: new ( bootsrc. as_str ( ) , "/boot" ) ;
311
- let kargs = vec ! [ rootarg, RW_KARG . to_string( ) , bootarg] ;
342
+ let kargs = root_blockdev_kargs
343
+ . into_iter ( )
344
+ . flatten ( )
345
+ . chain ( [ rootarg, RW_KARG . to_string ( ) , bootarg] . into_iter ( ) )
346
+ . collect :: < Vec < _ > > ( ) ;
312
347
313
- mount:: mount ( rootdev, & rootfs) ?;
348
+ mount:: mount ( & rootdev, & rootfs) ?;
314
349
lsm_label ( & rootfs, "/" . into ( ) , false ) ?;
315
350
let rootfs_fd = Dir :: open_ambient_dir ( & rootfs, cap_std:: ambient_authority ( ) ) ?;
316
351
let bootfs = rootfs. join ( "boot" ) ;
@@ -332,7 +367,12 @@ pub(crate) fn install_create_rootfs(
332
367
mount:: mount ( & espdev, & efifs_path) ?;
333
368
}
334
369
370
+ let luks_device = match opts. block_setup {
371
+ BlockSetup :: Direct => None ,
372
+ BlockSetup :: Tpm2Luks => Some ( luks_name. to_string ( ) ) ,
373
+ } ;
335
374
Ok ( RootSetup {
375
+ luks_device,
336
376
device,
337
377
rootfs,
338
378
rootfs_fd,
0 commit comments