@@ -8,8 +8,11 @@
#include <blk.h>
#include <command.h>
#include <dm.h>
+#include <hexdump.h>
#include <luks.h>
#include <part.h>
+#include <tkey.h>
+#include <u-boot/sha256.h>
static int do_luks_detect(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
@@ -57,18 +60,86 @@ static int do_luks_info(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_SUCCESS;
}
+/**
+ * unlock_with_tkey() - Unlock LUKS partition using TKey-derived key
+ *
+ * This function uses TKey to derive a disk encryption key from the
+ * provided passphrase (used as USS) and uses it to unlock the LUKS partition.
+ *
+ * @dev_desc: Block device descriptor
+ * @info: Partition information
+ * @passphrase: Passphrase to use as USS for TKey
+ * @master_key: Buffer to receive unlocked master key
+ * @key_size: Pointer to receive key size
+ * Return: 0 on success, -ve on error
+ */
+static int unlock_with_tkey(struct blk_desc *dev_desc,
+ struct disk_partition *info, const char *passphrase,
+ u8 *master_key, u32 *key_size)
+{
+ u8 tkey_disk_key[TKEY_DISK_KEY_SIZE];
+ u8 pubkey[TKEY_PUBKEY_SIZE];
+ struct udevice *tkey_dev;
+ int ret;
+
+ 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;
+ }
+
+ /* Derive disk key using TKey with passphrase as USS */
+ printf("Loading TKey signer app (%lx bytes) with USS...\n",
+ TKEY_SIGNER_SIZE);
+ ret = tkey_derive_disk_key(tkey_dev, (const u8 *)__signer_1_0_0_begin,
+ TKEY_SIGNER_SIZE, (const u8 *)passphrase,
+ strlen(passphrase), tkey_disk_key, pubkey,
+ NULL);
+ if (ret) {
+ printf("Failed to derive TKey disk key (err %dE)\n", ret);
+ return ret;
+ }
+
+ printf("TKey public key: ");
+ print_hex_dump(" ", DUMP_PREFIX_NONE, 16, 1, pubkey,
+ TKEY_PUBKEY_SIZE, false);
+
+ printf("TKey disk key derived successfully\n");
+ printf("TKey derived disk key: ");
+ print_hex_dump(" ", DUMP_PREFIX_NONE, 16, 1, tkey_disk_key,
+ TKEY_DISK_KEY_SIZE, false);
+
+ ret = luks_unlock(dev_desc->bdev, info, tkey_disk_key,
+ TKEY_DISK_KEY_SIZE, true, master_key, key_size);
+
+ /* Wipe TKey disk key */
+ memset(tkey_disk_key, '\0', sizeof(tkey_disk_key));
+
+ return ret;
+}
+
static int do_luks_unlock(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
struct blk_desc *dev_desc;
struct disk_partition info;
struct udevice *blkmap_dev;
- const char *passphrase;
+ const char *passphrase = NULL;
+ bool use_tkey = 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;
+ argc--;
+ argv++;
+ }
if (argc != 4)
return CMD_RET_USAGE;
@@ -78,6 +149,10 @@ static int do_luks_unlock(struct cmd_tbl *cmdtp, int flag, int argc,
passphrase = argv[3];
+ log_debug("Partition start %llx blks %llx blksz%lx\n",
+ (unsigned long long)info.start, (unsigned long long)info.size,
+ (ulong)dev_desc->blksz);
+
/* Verify it's a LUKS partition */
version = luks_get_version(dev_desc->bdev, &info);
if (version < 0) {
@@ -87,9 +162,15 @@ static int do_luks_unlock(struct cmd_tbl *cmdtp, int flag, int argc,
printf("Unlocking LUKS%d partition...\n", version);
- /* Unlock the partition to get the master key */
- ret = luks_unlock(dev_desc->bdev, &info, (const u8 *)passphrase,
- strlen(passphrase), false, master_key, &key_size);
+ if (use_tkey) {
+ ret = unlock_with_tkey(dev_desc, &info, passphrase, master_key,
+ &key_size);
+ } else {
+ /* Unlock with passphrase */
+ ret = luks_unlock(dev_desc->bdev, &info,(const u8 *)passphrase,
+ strlen(passphrase), false, master_key,
+ &key_size);
+ }
if (ret) {
printf("Failed to unlock LUKS partition (err %dE)\n", ret);
return CMD_RET_FAILURE;
@@ -121,10 +202,11 @@ 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 <interface> <dev[:part]> <passphrase> - unlock LUKS partition\n";
+ "luks unlock [-t] <interface> <dev[:part]> <passphrase> - unlock LUKS partition\n"
+ " -t: Use TKey hardware security token with passphrase as USS\n";
U_BOOT_CMD_WITH_SUBCMDS(luks, "LUKS (Linux Unified Key Setup) operations",
luks_help_text,
U_BOOT_SUBCMD_MKENT(detect, 3, 1, do_luks_detect),
U_BOOT_SUBCMD_MKENT(info, 3, 1, do_luks_info),
- U_BOOT_SUBCMD_MKENT(unlock, 4, 1, do_luks_unlock));
+ U_BOOT_SUBCMD_MKENT(unlock, 5, 1, do_luks_unlock));
@@ -13,7 +13,7 @@ Synopsis
luks detect <interface> <dev[:part]>
luks info <interface> <dev[:part]>
- luks unlock <interface> <dev[:part]> <passphrase>
+ luks unlock [-t] <interface> <dev[:part]> <passphrase>
Description
-----------
@@ -88,12 +88,17 @@ dev[:part]
luks unlock
~~~~~~~~~~~
-Unlock a LUKS encrypted partition using a passphrase. This command:
+Unlock a LUKS encrypted partition using a passphrase or TKey hardware token.
+This command:
1. Verifies the partition is LUKS encrypted (LUKS1 or LUKS2)
2. Parses LUKS2 JSON metadata (if LUKS2) using FDT conversion
-3. Derives the encryption key using PBKDF2 or Argon2id with the provided
- passphrase
+3. Derives the encryption key:
+
+ - **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
+
4. Attempts to unlock each active key slot
5. Verifies the master key against the stored digest
6. Creates a blkmap device providing on-the-fly decryption
@@ -118,6 +123,11 @@ be used to access files on the unlocked partition.
* **Argon2id**: Memory-hard KDF resistant to GPU attacks (LUKS2 only, requires
CONFIG_ARGON2)
+-t
+ Optional flag to use TKey hardware security token. When specified, the
+ passphrase is used as the USS (User-Supplied Secret) to derive a disk
+ encryption key from the TKey's public key.
+
interface
The storage interface type (e.g., mmc, usb, scsi)
@@ -125,7 +135,8 @@ dev[:part]
The device number and optional partition number
passphrase
- The passphrase to unlock the LUKS partition. Note that the passphrase is
+ The passphrase to unlock the LUKS partition. When using -t flag, this is
+ used as the USS for TKey key derivation. Note that the passphrase is
passed as a command-line argument and may be visible in command history.
Consider using environment variables to minimize exposure.
@@ -228,6 +239,17 @@ Unlock and load a kernel from encrypted partition::
=> bootz ${kernel_addr_r} - ${fdt_addr_r}
+Unlock using TKey hardware token::
+
+ => luks unlock -t mmc 0:2 mypassword
+ Using TKey for disk encryption key
+ Loading TKey signer app (7168 bytes) with USS...
+ TKey public key: 3a b2 c4 ... (32 bytes)
+ TKey disk key derived successfully
+ Unlocking LUKS2 partition...
+ Successfully unlocked with key slot 0!
+ Unlocked LUKS partition as blkmap device 'luks-mmc-0:2'
+
Configuration
-------------
@@ -254,6 +276,10 @@ For Argon2id support (modern LUKS2 KDF)::
CONFIG_ARGON2=y # Argon2 password hashing (adds ~50KB to binary)
+For TKey hardware token support (requires -t flag)::
+
+ CONFIG_TKEY=y # TKey hardware security token support
+
Return value
------------