Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for unlocking LUKS with a key file #37

Closed
joserebelo opened this issue Feb 24, 2021 · 9 comments
Closed

Add support for unlocking LUKS with a key file #37

joserebelo opened this issue Feb 24, 2021 · 9 comments
Milestone

Comments

@joserebelo
Copy link

It would be nice if something like the encrypt hook cryptkey or sd-encrypt's rd.luks.key was supported, allowing for the root partition to be unlocked with a key file.

More info: https://wiki.archlinux.org/index.php/Dm-crypt/System_configuration#rd.luks.key

@joserebelo joserebelo changed the title Add support for LUKS keyfile Add support for unlocking LUKS with a key file Feb 24, 2021
@gadgethm
Copy link

I also would like this support, as I use a TPM to automatically unlock my encrypted drive.

@anatol anatol added this to the 0.8 milestone Apr 9, 2022
@anatol anatol modified the milestones: 0.8, 0.9 May 6, 2022
anatol pushed a commit to jacobmyers-codeninja/booster that referenced this issue Aug 13, 2022
...reworked the luks mappings a little to allow more complex patterns of parsing parameters and building mappings.

This slightly tweaks creating luksMapping lists so they can occur multiple times in the kernel parameter list and it just updates the relevant properties for each mapping (to allow extending even further if desired).

updated luksMapping type to hold a keyfile
add a luksMapping findOrCreate function in luks.go, either finds the existing mapping by UUID or adds one
update the rd.luks.uuid and rd.luks.name in cmdline.go to make use of findOrCreate
adds rd.luks.key with the format UUID=keyfile which should point to a file in initramfs containing the password
adds recoverKeyfilePassword go routine which attempts to read the password from the keyfile and unlock the device, falling back to running the requestKeyboardPassword option if that fails
update luksOpen to call recoverKeyfilePassword if a keyfile is defined on the mapping
Putting this forward more as an idea for the approach, not sure how good or bad the specific way I implemented it is.

Implements anatol#37
anatol pushed a commit to jacobmyers-codeninja/booster that referenced this issue Aug 13, 2022
...reworked the luks mappings a little to allow more complex patterns of parsing parameters and building mappings.

This slightly tweaks creating luksMapping lists so they can occur multiple times in the kernel parameter list and it just updates the relevant properties for each mapping (to allow extending even further if desired).

updated luksMapping type to hold a keyfile
add a luksMapping findOrCreate function in luks.go, either finds the existing mapping by UUID or adds one
update the rd.luks.uuid and rd.luks.name in cmdline.go to make use of findOrCreate
adds rd.luks.key with the format UUID=keyfile which should point to a file in initramfs containing the password
adds recoverKeyfilePassword go routine which attempts to read the password from the keyfile and unlock the device, falling back to running the requestKeyboardPassword option if that fails
update luksOpen to call recoverKeyfilePassword if a keyfile is defined on the mapping
Putting this forward more as an idea for the approach, not sure how good or bad the specific way I implemented it is.

Implements anatol#37
anatol pushed a commit to jacobmyers-codeninja/booster that referenced this issue Aug 14, 2022
...reworked the luks mappings a little to allow more complex patterns of parsing parameters and building mappings.

This slightly tweaks creating luksMapping lists so they can occur multiple times in the kernel parameter list and it just updates the relevant properties for each mapping (to allow extending even further if desired).

updated luksMapping type to hold a keyfile
add a luksMapping findOrCreate function in luks.go, either finds the existing mapping by UUID or adds one
update the rd.luks.uuid and rd.luks.name in cmdline.go to make use of findOrCreate
adds rd.luks.key with the format UUID=keyfile which should point to a file in initramfs containing the password
adds recoverKeyfilePassword go routine which attempts to read the password from the keyfile and unlock the device, falling back to running the requestKeyboardPassword option if that fails
update luksOpen to call recoverKeyfilePassword if a keyfile is defined on the mapping
Putting this forward more as an idea for the approach, not sure how good or bad the specific way I implemented it is.

Implements anatol#37
anatol pushed a commit that referenced this issue Aug 14, 2022
...reworked the luks mappings a little to allow more complex patterns of parsing parameters and building mappings.

This slightly tweaks creating luksMapping lists so they can occur multiple times in the kernel parameter list and it just updates the relevant properties for each mapping (to allow extending even further if desired).

updated luksMapping type to hold a keyfile
add a luksMapping findOrCreate function in luks.go, either finds the existing mapping by UUID or adds one
update the rd.luks.uuid and rd.luks.name in cmdline.go to make use of findOrCreate
adds rd.luks.key with the format UUID=keyfile which should point to a file in initramfs containing the password
adds recoverKeyfilePassword go routine which attempts to read the password from the keyfile and unlock the device, falling back to running the requestKeyboardPassword option if that fails
update luksOpen to call recoverKeyfilePassword if a keyfile is defined on the mapping
Putting this forward more as an idea for the approach, not sure how good or bad the specific way I implemented it is.

Implements #37
anatol pushed a commit that referenced this issue Aug 18, 2022
...reworked the luks mappings a little to allow more complex patterns of parsing parameters and building mappings.

This slightly tweaks creating luksMapping lists so they can occur multiple times in the kernel parameter list and it just updates the relevant properties for each mapping (to allow extending even further if desired).

updated luksMapping type to hold a keyfile
add a luksMapping findOrCreate function in luks.go, either finds the existing mapping by UUID or adds one
update the rd.luks.uuid and rd.luks.name in cmdline.go to make use of findOrCreate
adds rd.luks.key with the format UUID=keyfile which should point to a file in initramfs containing the password
adds recoverKeyfilePassword go routine which attempts to read the password from the keyfile and unlock the device, falling back to running the requestKeyboardPassword option if that fails
update luksOpen to call recoverKeyfilePassword if a keyfile is defined on the mapping
Putting this forward more as an idea for the approach, not sure how good or bad the specific way I implemented it is.

Implements #37
@dkwo
Copy link

dkwo commented Nov 26, 2022

Just a quick question: is this now implemented? if so, does it mean one can use yubikey with booster? or is it in progress?
Thanks.

@anatol
Copy link
Owner

anatol commented Dec 22, 2022

@dkwo the feature is implemented now. See jacobmyers-codeninja@ab56ce5#diff-202700f9afad82959d12d36af398c56ad7a0e5223da8382e5a4aced3253da171

Note that the keyfile must live at the initramfs.

@anatol anatol closed this as completed Dec 22, 2022
@Barbaross93
Copy link

If we want to include the key file within the initramfs, then would we want to include it with the extra_files: ... option?

@Barbaross93
Copy link

Nevermind, that does seem to be the way to do it. Unfortunately, this doesn't seem to be very secure for unlocking the root partition. Support for specifying a key file on a separate disk, e.g. a USB stick would be ideal. Are/is there any plans/interest in expanding on this feature?

Alternatively, and I can make a separate issue for this, how does the clevis style binding of LUKS work with booster? I'm running on Void Linux which doesn't have systemd or clevis currently in the repos. There are some tpm2 utilities in the repos, so a manual way of binding LUKS with the tpm could be possible for my use case. I'm just unsure of what commands need to be run.

@anatol
Copy link
Owner

anatol commented Mar 21, 2023

Support for specifying a key file on a separate disk, e.g. a USB stick would be ideal.

Yes, the plan is to support following features:

  1. reading the unlock key from a file at $EFI
  2. (optionally) read key from a block device by its offset and key length (e.g. "read key from UUID=283983423 offset=4096 length=1024")

how does the clevis style binding of LUKS work with booster?

Booster has a great support for Clevis style binding (Tang/TPM2/SSS) plus it supports custom Yubikey Challenge-Response binding.

In addition to that Booster supports Systemd TPM Fido style binding.

I'm just unsure of what commands need to be run.

The best option is to add clevis and tang packages to Void repo. And then use the standard enrollment operations.

@anatol
Copy link
Owner

anatol commented Mar 21, 2023

PS I wish cryptsetup maintainers added support for in-application enrollment using its API [1]. In this case no clevis tools would be needed - just cryptsetup plus my plugin https://github.com/anatol/clevis.go/blob/main/cryptsetup-plugin/main.go would be enough.

[1] https://gitlab.com/cryptsetup/cryptsetup/-/issues/726

@Barbaross93
Copy link

Support for specifying a key file on a separate disk, e.g. a USB stick would be ideal.

Yes, the plan is to support following features:

1. reading the unlock key from a file at $EFI

2. (optionally) read key from a block device by its offset and key length (e.g. "read key from UUID=283983423 offset=4096 length=1024")

Awesome, I'm glad that's on the radar! Will offset and length be required parameters? It might be more user friendly to specify a file path instead.

how does the clevis style binding of LUKS work with booster?

Booster has a great support for Clevis style binding (Tang/TPM2/SSS) plus it supports custom Yubikey Challenge-Response binding.

In addition to that Booster supports Systemd TPM Fido style binding.

I'm just unsure of what commands need to be run.

The best option is to add clevis and tang packages to Void repo. And then use the standard enrollment operations.

I was hoping for a more mechanistic explanation, i.e. what does booster look for exactly in order to do what clevis does manually. It sounds like booster depends on clevis for that functionality, so a manual route isn't possible if I understand you correctly.

PS I wish cryptsetup maintainers added support for in-application enrollment using its API [1]. In this case no clevis tools would be needed - just cryptsetup plus my plugin https://github.com/anatol/clevis.go/blob/main/cryptsetup-plugin/main.go would be enough.

[1] https://gitlab.com/cryptsetup/cryptsetup/-/issues/726

This indeed seems like the most ideal solution of all. Maybe some day :(

@anatol
Copy link
Owner

anatol commented Mar 21, 2023

It might be more user friendly to specify a file path instead.

It will support both ways eventually. By filename, and by device+offset+length for a steganography-style setup.

I was hoping for a more mechanistic explanation, i.e. what does booster look for exactly in order to do what clevis does manually. It sounds like booster depends on clevis for that functionality, so a manual route isn't possible if I understand you correctly.

Booster uses my other library called clevis.go that implements clevis encrypt/decrypt functionality. This file in particular deals with TPM2 pin unbinding https://github.com/anatol/clevis.go/blob/main/tpm2.go#L238

clevis.go does not have a command line tool yet (like clevis package). But if you are interested to learn clevis internals adding a cmd tool would be a great way to learn it and a great contribution to the project.

This indeed seems like the most ideal solution of all. Maybe some day :(

One way to speed up the feature implementation is to keep checking with them. If enough people come with valid requests they might finally implement the feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants