From patchwork Sun Nov 16 21:23:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 728 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org Authentication-Results: mail.u-boot.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=GnMnv+Qu; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id A249B685FE for ; Sun, 16 Nov 2025 14:24:26 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id rmBgZE_uhy7r for ; Sun, 16 Nov 2025 14:24:26 -0700 (MST) Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id AE1446864C for ; Sun, 16 Nov 2025 14:24:24 -0700 (MST) Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 99651684C5 for ; Sun, 16 Nov 2025 14:24:22 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id TE3VgrZRSTj0 for ; Sun, 16 Nov 2025 14:24:22 -0700 (MST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=209.85.166.49; helo=mail-io1-f49.google.com; envelope-from=sjg@chromium.org; receiver=u-boot.org Received: from mail-io1-f49.google.com (mail-io1-f49.google.com [209.85.166.49]) by mail.u-boot.org (Postfix) with ESMTPS id CA57568641 for ; Sun, 16 Nov 2025 14:24:20 -0700 (MST) Received: by mail-io1-f49.google.com with SMTP id ca18e2360f4ac-94880a46f3fso112039439f.2 for ; Sun, 16 Nov 2025 13:24:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1763328259; x=1763933059; darn=u-boot.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jlqI9bRY37tfsnqw+zSi4scRbQWESX7SbhgZk1FSL7M=; b=GnMnv+QukQ0Exs8tPERUutPypOs3OVKhWkZis5Kh6eD5XGGwd8Esu5KMAKSXnZE1+V FSpe1TmeOqrJh5qM0fYTEDpHDkc2fdIoT0aEBw4xFLvUz/IHTJB7vC/zcQKEt6PBC9Kb HIXwx6apAhq+pw77o8JwlOMk3Wfnbb8kYhjag= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763328259; x=1763933059; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=jlqI9bRY37tfsnqw+zSi4scRbQWESX7SbhgZk1FSL7M=; b=j+onVOUKD8ty6/Egy/NPrYi/wfFzI+jUi2YdaRShGtTxX/sVzOG8XhFOb7QKip7THK UtoJYHHmEsGo3QkYAxgE4S26YgrfgQ65Krlag4eJ5uKPwiQ1SVG3dYT+MyR74n8wVEeY 93lAaLNfGvFElo8x8JGCjslf++qNRkO/STCV9dCHM7RikJRW7FP70MR0Gjynt6nCXtM2 l/GF+nl4/j9qy0EQO5kXqMc+h1VqN0jCfenV1e5oHO91/zYgaDtmUi7ugzNg7x9/iH7j Bu5PNGL/zCFjs5C5WB79KZiVyb7tml2YzzHwQH4laV4ihity7rkpL6Pc4U9hcWiCaY5Q y+zw== X-Gm-Message-State: AOJu0YzfH8y6yqfveffYbDAuheyudxOU57WbGVVgRfRkyt9Ou0W7pml7 CGTrwnRE4ckc4KugEcZgSgZeQ0m5V2R3OWtzko2oqP5wJCM992Ra3K4WHIrEMLnN9kH2dHNBIq8 WlmQ= X-Gm-Gg: ASbGncumLh5XnO3ZG/P93KG4CZC2opmtgistUNOOuFY6hZzQn67RZhKBIm7QY9hdice jfivxW8cgIjhBbTIte8Zq8+GMIGuzY7Ktup7rAAdfKn9wN4EeZdIWwYehbBIx8CFrCblQqzvU54 UMItqdlwBNDgnSovzqKD5T+2D6QgwtA3rvRvIDQaQdh07WXCHF47DEsRmAYWl/Qvu1+oGSYyXEl HKBwqk8/vUfnoGOz6+/34uLWeJIR5taOAbWNL6cghka9Z4e9hbkG+eCH7QNTufaNRhFWgMfxL4H hNwcMhkVXKbrgEN3DnlDGZQbRNOUhgad8mF1TWWMxoBr8+AdUKRdxSHpKu6KJjIsp2Tk1gL0b8M MQzxTNr9QdD3Jhbncmq4cKr733F8eZju7U8tCy6MfjarmwaC5/sCZqbNsdalfXmi4H0k8gws89H W9qQvdCUecAAOgUHX7 X-Google-Smtp-Source: AGHT+IHJpGv3gTM/w6OprRVEKXBEziuIDYj9K9/JXUoop9MPLYl/+PnepS54jzfXFZWNIXWjYUY2tQ== X-Received: by 2002:a05:6602:1344:b0:945:a27d:d4a6 with SMTP id ca18e2360f4ac-948e0d640d6mr1204433439f.12.1763328259317; Sun, 16 Nov 2025 13:24:19 -0800 (PST) Received: from chromium.org ([73.34.74.121]) by smtp.gmail.com with ESMTPSA id ca18e2360f4ac-948d2d162dcsm577962339f.13.2025.11.16.13.24.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Nov 2025 13:24:17 -0800 (PST) From: Simon Glass X-Google-Original-From: Simon Glass To: U-Boot Concept Date: Sun, 16 Nov 2025 14:23:28 -0700 Message-ID: <20251116212334.1603490-15-simon.glass@canonical.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251116212334.1603490-1-simon.glass@canonical.com> References: <20251116212334.1603490-1-simon.glass@canonical.com> MIME-Version: 1.0 Message-ID-Hash: PSXDJFG5EX227FUURAVGCMYQKNG5XRGM X-Message-ID-Hash: PSXDJFG5EX227FUURAVGCMYQKNG5XRGM X-MailFrom: sjg@chromium.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 14/14] luks: Support disk unlock using a TKey List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Add a -t option to the 'luks unlock' command to allow a TKey to be used to unlock a disk. The password is used as the user-supplied secret (USS) in this case. Co-developed-by: Claude Signed-off-by: Simon Glass --- cmd/luks.c | 94 +++++++++++++++++++++++++++++++++++++++--- doc/usage/cmd/luks.rst | 36 +++++++++++++--- 2 files changed, 119 insertions(+), 11 deletions(-) diff --git a/cmd/luks.c b/cmd/luks.c index 47d3e5bed7b..ec4d400b44e 100644 --- a/cmd/luks.c +++ b/cmd/luks.c @@ -8,8 +8,11 @@ #include #include #include +#include #include #include +#include +#include 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 - detect if partition is LUKS encrypted\n" "luks info - show LUKS header information\n" - "luks unlock - unlock LUKS partition\n"; + "luks unlock [-t] - 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)); diff --git a/doc/usage/cmd/luks.rst b/doc/usage/cmd/luks.rst index 3c8576dc8a1..ccf915f5844 100644 --- a/doc/usage/cmd/luks.rst +++ b/doc/usage/cmd/luks.rst @@ -13,7 +13,7 @@ Synopsis luks detect luks info - luks unlock + luks unlock [-t] 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 ------------