luks: Add -p flag for pre-derived master key
Add a -p flag to the luks unlock command that allows passing a hex-encoded pre-derived master key, skipping the KDF step. This is useful when the master key has been derived externally, such as from a hardware security module. Adjust the normal flow (without -p) to use a key derived on the TKey output. While that works OK with LUKS1, the 32-byte value is not long enough to work with LUKS2. Update the documentation to describe the new flag. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com>
This commit is contained in:
42
cmd/luks.c
42
cmd/luks.c
@@ -85,10 +85,10 @@ static int unlock_with_tkey(struct blk_desc *dev_desc,
|
||||
printf("Using TKey for disk encryption key\n");
|
||||
|
||||
/* Find TKey device */
|
||||
ret = uclass_first_device_err(UCLASS_TKEY, &tkey_dev);
|
||||
if (ret) {
|
||||
printf("Failed to find TKey device (err %dE)\n", ret);
|
||||
return ret;
|
||||
tkey_dev = tkey_get_device();
|
||||
if (!tkey_dev) {
|
||||
printf("Failed to find TKey device\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Derive disk key using TKey with passphrase as USS */
|
||||
@@ -113,7 +113,7 @@ static int unlock_with_tkey(struct blk_desc *dev_desc,
|
||||
TKEY_DISK_KEY_SIZE, false);
|
||||
|
||||
ret = luks_unlock(dev_desc->bdev, info, tkey_disk_key,
|
||||
TKEY_DISK_KEY_SIZE, true, master_key, key_size);
|
||||
TKEY_DISK_KEY_SIZE, false, master_key, key_size);
|
||||
|
||||
/* Wipe TKey disk key */
|
||||
memset(tkey_disk_key, '\0', sizeof(tkey_disk_key));
|
||||
@@ -129,14 +129,21 @@ static int do_luks_unlock(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
struct udevice *blkmap_dev;
|
||||
const char *passphrase = NULL;
|
||||
bool use_tkey = false;
|
||||
bool pre_derived = false;
|
||||
int part, ret, version;
|
||||
u8 master_key[128];
|
||||
char label[64];
|
||||
u32 key_size;
|
||||
|
||||
/* Check for -t flag */
|
||||
if (!strcmp(argv[1], "-t")) {
|
||||
use_tkey = true;
|
||||
/* Check for flags */
|
||||
while (argc > 1 && argv[1][0] == '-') {
|
||||
if (!strcmp(argv[1], "-t")) {
|
||||
use_tkey = true;
|
||||
} else if (!strcmp(argv[1], "-p")) {
|
||||
pre_derived = true;
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
@@ -165,9 +172,21 @@ static int do_luks_unlock(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
if (use_tkey) {
|
||||
ret = unlock_with_tkey(dev_desc, &info, passphrase, master_key,
|
||||
&key_size);
|
||||
} else if (pre_derived) {
|
||||
/* Pre-derived key: passphrase is hex-encoded master key */
|
||||
u8 key_buf[64];
|
||||
size_t key_len = strlen(passphrase) / 2;
|
||||
|
||||
if (key_len > sizeof(key_buf) || hex2bin(key_buf, passphrase,
|
||||
key_len)) {
|
||||
printf("Invalid hex key\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
ret = luks_unlock(dev_desc->bdev, &info, key_buf, key_len,
|
||||
true, master_key, &key_size);
|
||||
} else {
|
||||
/* Unlock with passphrase */
|
||||
ret = luks_unlock(dev_desc->bdev, &info,(const u8 *)passphrase,
|
||||
ret = luks_unlock(dev_desc->bdev, &info, (const u8 *)passphrase,
|
||||
strlen(passphrase), false, master_key,
|
||||
&key_size);
|
||||
}
|
||||
@@ -202,8 +221,9 @@ cleanup:
|
||||
static char luks_help_text[] =
|
||||
"detect <interface> <dev[:part]> - detect if partition is LUKS encrypted\n"
|
||||
"luks info <interface> <dev[:part]> - show LUKS header information\n"
|
||||
"luks unlock [-t] <interface> <dev[:part]> <passphrase> - unlock LUKS partition\n"
|
||||
" -t: Use TKey hardware security token with passphrase as USS\n";
|
||||
"luks unlock [-t] [-p] <interface> <dev[:part]> <passphrase> - unlock LUKS partition\n"
|
||||
" -t: Use TKey hardware security token with passphrase as USS\n"
|
||||
" -p: Treat passphrase as hex-encoded pre-derived master key (skip KDF)\n";
|
||||
|
||||
U_BOOT_CMD_WITH_SUBCMDS(luks, "LUKS (Linux Unified Key Setup) operations",
|
||||
luks_help_text,
|
||||
|
||||
@@ -13,7 +13,7 @@ Synopsis
|
||||
|
||||
luks detect <interface> <dev[:part]>
|
||||
luks info <interface> <dev[:part]>
|
||||
luks unlock [-t] <interface> <dev[:part]> <passphrase>
|
||||
luks unlock [-t] [-p] <interface> <dev[:part]> <passphrase>
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -97,7 +97,8 @@ This command:
|
||||
|
||||
- **Without -t**: Uses PBKDF2 or Argon2id with the provided passphrase
|
||||
- **With -t**: Uses TKey hardware token with passphrase as USS (User-Supplied
|
||||
Secret) to derive a disk encryption key
|
||||
Secret) to derive a disk encryption key. You can use 'tkey connect' to
|
||||
select which TKey to use, otherwise it uses the first one it finds.
|
||||
|
||||
4. Attempts to unlock each active key slot
|
||||
5. Verifies the master key against the stored digest
|
||||
@@ -128,6 +129,12 @@ be used to access files on the unlocked partition.
|
||||
passphrase is used as the USS (User-Supplied Secret) to derive a disk
|
||||
encryption key from the TKey's public key.
|
||||
|
||||
-p
|
||||
Optional flag to treat the passphrase as a hex-encoded pre-derived master
|
||||
key, skipping the KDF (Key Derivation Function) step. This is useful when
|
||||
the master key has already been derived externally, such as from a hardware
|
||||
security module or other key management system.
|
||||
|
||||
interface
|
||||
The storage interface type (e.g., mmc, usb, scsi)
|
||||
|
||||
@@ -250,6 +257,13 @@ Unlock using TKey hardware token::
|
||||
Successfully unlocked with key slot 0!
|
||||
Unlocked LUKS partition as blkmap device 'luks-mmc-0:2'
|
||||
|
||||
Unlock using a pre-derived master key (hex-encoded)::
|
||||
|
||||
=> luks unlock -p mmc 0:2 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
||||
Unlocking LUKS2 partition...
|
||||
Successfully unlocked with key slot 0!
|
||||
Unlocked LUKS partition as blkmap device 'luks-mmc-0:2'
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user