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

Fail to unlock LUKS by password #202

Closed
ZJaume opened this issue Jan 5, 2023 · 16 comments
Closed

Fail to unlock LUKS by password #202

ZJaume opened this issue Jan 5, 2023 · 16 comments

Comments

@ZJaume
Copy link

ZJaume commented Jan 5, 2023

I'm booting Arch with a booster UKI bundled with sbctl (maybe this is causing the issue?) and have LVM on LUKS for root partition. Booster is asking for the passphrase but no matter what it always fails.
imatge

My password does not have any special character but I enabled vconsole anyway to see if it was a problem with the keymap, but the same. I've also tried to add a very simple password entry but it also fails. The LUKS partition is ok because I'm currently able to boot through a dracut image. I don't know if booster works on my machine bundling the image with a bootloader because I have an encrypted boot and it's a bit more complicated to configure anything that is not an UKI.

This is the current config:

enable_lvm: true
strip: false
universal: true
mount_timeout: 1m
vconsole: true
extra_files: busybox,fsck,fsck.ext4

EDIT: commands to generate the image:

sudo booster build -f /boot/booster-linux.img
sudo sbctl bundle -a /boot/amd-ucode.img -f /boot/booster-linux.img /efi/Linux/archlinux.efi

and the content of /etc/kernel/cmdline which is sourced by sbctl:

rd.luks.name=UUID=cryptolvm rd.luks.options=discard root=/dev/mapper/root rootfstype=ext4 rootflags=rw,relatime,data=ordered
@anatol
Copy link
Owner

anatol commented Jan 7, 2023

In your boot parameters you specify crypt device name cryptolvm. It will add /dev/mapper/cryptolvm device file.

But your root is /dev/mapper/root and booster never sees such device, thus times out.

Try to change root to root=/dev/mapper/cryptolvm and see if it makes any difference for you.

@anatol
Copy link
Owner

anatol commented Jan 7, 2023

Also why there are so many password retries for cryptolvm? Did you enter an invalid password? Or is it some problem with booster?

@ZJaume
Copy link
Author

ZJaume commented Jan 7, 2023

Sorry about the confusion, I was hiding the real name of the root volume. The scheme is an LVM on LUKS and the parameter real value is root=/dev/mapper/Vol-root, so I guess it's ok, right? It's been like that with mkinitcpio and was working well.

Also why there are so many password retries for cryptolvm ? Did you enter an invalid password? Or is it some problem with booster?

That is reason of my question. I was writing the right password. I tried many times and always giving me this. Furthermore, I'm able to boot through another efi binary that has been bundled with the mkinitcpio, so the partition and the password are ok.

If we need to debug this, is there any way of testing the booster decryption separately? Maybe a simple small program to open it using the luks go module? I've enable the debug mode and no other messages appear during the unlocking attempts.

@anatol
Copy link
Owner

anatol commented Jan 8, 2023

LVM on LUKS and the parameter real value is root=/dev/mapper/Vol-root, so I guess it's ok, right?

LVM-on-LUKS is supported by booster. So it should be fine.

The best way to start debugging is to enable debug logs with booster.debug kernel parameter. It will print a lot of information to the console. Once you type the password it will print the reason why the password did not match. It will give clues on what is going on at your host.

@ZJaume
Copy link
Author

ZJaume commented Jan 10, 2023

The debug option does not say anything more. Just incorrect password during the attempts.
imatge

@anatol
Copy link
Owner

anatol commented Jan 13, 2023

It is a weird issue. If the password failed due to some missing modules, then an error message would be printed. But here we have no any messages.

Are you sure you type the correct password for cryprolvm? Do you use non-ASCII symbols in your password? Do you have non-English keyboard that needs to be configured?

I would start with trying the latest changes from master branch and see if the problem still exists. Then try to modify requestKeyboardPassword() function

func requestKeyboardPassword(volumes chan *luks.Volume, d luks.Device, checkSlots []int, mappingName string) {
and print the entered password just to make sure it is precisely the same as expected.

Also, do you use any non-standard cyphers/hash functions for your LUKS partition? Do you remember how did you format it?

@ZJaume
Copy link
Author

ZJaume commented Jan 14, 2023

The password doesn't seem to be the problem neither the keyboard. I have an Spanish keyboard, but the main password does not have any non-ASCII character. Furthermore, I added vconsole module and mount timeout, and when the console starts, I type the password and the characters are correct. I've also tried to add a new keyslot, with a dummy password (1234) but didn't work neither. I never used any custom parameter when adding keyslots. They key derivation functions are pkdf2 for the old one and argon2id for the dummy, both are standard and supported, right? The only thing that could be strange in my partition is that it was LUKS1 and I converted it to LUKS2 when it came out. But mkinitcpio has always been able to decrypt it.

I've tried master with the booster-git package from the aur, plus adding some debug messages and didn't work.

This is the code:

diff --git a/init/luks.go b/init/luks.go
index 8845f60..0ebc392 100644
--- a/init/luks.go
+++ b/init/luks.go
@@ -364,6 +364,7 @@ func requestKeyboardPassword(volumes chan *luks.Volume, d luks.Device, checkSlot
        for {
                prompt := fmt.Sprintf("Enter passphrase for %s:", mappingName)
                password, err := readPassword(prompt, "   Unlocking...")
+                debug("entered password: %s", password)
                if err != nil {
                        warning("reading password: %v", err)
                        return
@@ -373,8 +374,10 @@ func requestKeyboardPassword(volumes chan *luks.Volume, d luks.Device, checkSlot
                }

                for _, s := range checkSlots {
+                        debug("trying slot %v", s)
                        v, err := d.UnsealVolume(s, password)
                        if err == luks.ErrPassphraseDoesNotMatch {
+                                debug("passphrase does not match for slot %v", s)
                                continue
                        } else if err != nil {
                                warning("unlocking slot %v: %v", s, err)

and the messages trying the dummy password that I added for debugging purposes:
imatge

The command that I've used to add this new slot was cryptsetup luksAddKey /dev/nvme0n1p2 and for the migration it was cryptsetup format --type luks2 /dev/nvme0n1p2.

@anatol
Copy link
Owner

anatol commented Jan 15, 2023

and for the migration it was cryptsetup format --type luks2 /dev/nvme0n1p2.

I believe you need to use cryptsetup convert tool for format conversion.

They key derivation functions are pkdf2 for the old one and argon2id for the dummy, both are standard and supported, right?

Correct, both derivation functions are supported. If the problem was related to a missing algorithm it would print an error message.

Could you please provide the luks partition info with cryptsetup luksDump /dev/nvme0n1p2? (clear Salt/Digest fields before sharing it).

@ZJaume
Copy link
Author

ZJaume commented Jan 15, 2023

I believe you need to use cryptsetup convert tool for format conversion.

I didn't remember that command, I suppose that I used that.

Could you please provide the luks partition info with cryptsetup luksDump /dev/nvme0n1p2? (clear Salt/Digest fields before sharing it).

Sure, this is the whole output of the command, omitting salts, digests and UUID.

LUKS header information
Version:       	2
Epoch:         	14
Metadata area: 	16384 [bytes]
Keyslots area: 	2064384 [bytes]
UUID:          	
Label:         	(no label)
Subsystem:     	(no subsystem)
Flags:       	(no flags)

Data segments:
  0: crypt
	offset: 2097152 [bytes]
	length: (whole device)
	cipher: aes-xts-plain64
	sector: 512 [bytes]

Keyslots:
  0: luks2
	Key:        256 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 256 bits
	PBKDF:      pbkdf2
	Hash:       sha256
	Iterations: 2267994
	Salt:       
	            
	AF stripes: 4000
	AF hash:    sha256
	Area offset:32768 [bytes]
	Area length:131072 [bytes]
	Digest ID:  0
  1: luks2
	Key:        256 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 256 bits
	PBKDF:      argon2id
	Time cost:  7
	Memory:     1048576
	Threads:    4
	Salt:       
	            
	AF stripes: 4000
	AF hash:    sha256
	Area offset:163840 [bytes]
	Area length:131072 [bytes]
	Digest ID:  0
  2: luks2
	Key:        256 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 256 bits
	PBKDF:      argon2id
	Time cost:  6
	Memory:     1048576
	Threads:    4
	Salt:       
	            
	AF stripes: 4000
	AF hash:    sha256
	Area offset:294912 [bytes]
	Area length:131072 [bytes]
	Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
	Hash:       sha256
	Iterations: 283250
	Salt:       
	            
	Digest: 

EDIT: I also realised that I had no_read_workqueue and no_write_queue enabled as flags. I have now disabled those and retried, but the issue still persists.

@deathtrip
Copy link

I'm having the same problem, with LUKS2 (also converted from LUKS1) on LVM and ext4 as root filesystem. The password is good as i can boot with mkinitcpio image.
What's interesting is i can boot using booster into an different arch installation with XFS as rootfs , even on the same hardware and same booster and LUKS configs. However that installation was using LUKS2 from the beginning.
So maybe its the ext4 + LUKS/LVM combo that's causing this, or booster has some issue reading converted LUKS2 headers....
Will try to investigate further...

@deathtrip
Copy link

deathtrip commented Apr 9, 2023

After checking debug messages i got the unknown digest error : whirlpool. I forgot the other install was using sha-3, as the ciphers were the same.

However the error message should give the unknown cipher/digest error by default, without adding the debug kernel parameter, as i was getting the same Incorrect passphrase... error, which is confusing.

Anyway, i guess i'll have to wait until support is added, as per this issue.

@anatol
Copy link
Owner

anatol commented Apr 23, 2023

@deathtrip I just added whirlpool hash algorithm support to luks.go library:
anatol/luks.go@fb3724e

@deathtrip
Copy link

After trying the new release, i still can't unlock the volume with my password. Except now i don't get any unknown digest error warnings. The install without whirlpool works fine. So now i'm not sure if it's the hash or something else.

@nmeum
Copy link
Contributor

nmeum commented Dec 23, 2023

I'm having the same problem, with LUKS2 (also converted from LUKS1) on LVM and ext4 as root filesystem.

I am also running into this. I cannot open a LUKS2 device that was converted from LUKS1. As described in this issue, the password always seems wrong even though it is definitely correct. Prior to the conversion, booster worked fine. Additionally, I have other machines which use a freshly installed LUKS2 (instead of a converted one) where Booster also works fine.

I suppose cryptsetup convert results in a format that is somehow incompatible with Boosters LUKS code?

@nmeum
Copy link
Contributor

nmeum commented Dec 23, 2023

I am also running into this. I cannot open a LUKS2 device that was converted from LUKS1.

I debugged this further and this seems to be a bug in luks.go.

See: anatol/luks.go#11

nmeum added a commit to nmeum/luks.go that referenced this issue Dec 23, 2023
LUKS1 was limited to a 20 byte digest length. With LUKS2 this limitation
was lifted. However, it seems that for LUKS volumes which were converted
from LUKS1 to LUKS2, the digest length it still 20 bytes. This commit
proposes using the length of the expected digest to determine the digit
length in use. For this purpose, it only compares the first n bytes of
the generated digest with the expected digest.

This fixes compatibility of luks.go with volumes converted from LUKS1.

Fixes: anatol#11

See also: anatol/booster#202
nmeum added a commit to nmeum/luks.go that referenced this issue Dec 23, 2023
LUKS1 was limited to a 20 byte digest length. With LUKS2 this limitation
was lifted. However, it seems that for LUKS volumes which were converted
from LUKS1 to LUKS2, the digest length it still 20 bytes. This commit
proposes using the length of the expected digest to determine the digit
length in use. For this purpose, it only compares the first n bytes of
the generated digest with the expected digest.

This fixes compatibility of luks.go with volumes converted from LUKS1.

Fixes: anatol#11

See also: anatol/booster#202
@deathtrip
Copy link

I also only had problems on a device converted from LUKS1 to LUKS2.
OP was also using LUKS2 that was converted, so it looks like the cause of the problem is now known.
Hopefully the pull request to luks.go will be accepted soon.

anatol pushed a commit to anatol/luks.go that referenced this issue May 7, 2024
LUKS1 was limited to a 20 byte digest length. With LUKS2 this limitation
was lifted. However, it seems that for LUKS volumes which were converted
from LUKS1 to LUKS2, the digest length it still 20 bytes. This commit
proposes using the length of the expected digest to determine the digit
length in use. For this purpose, it only compares the first n bytes of
the generated digest with the expected digest.

This fixes compatibility of luks.go with volumes converted from LUKS1.

Fixes: #11

See also: anatol/booster#202
@anatol anatol closed this as completed in d3295eb May 14, 2024
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

4 participants