diff --git a/doc/usage/cmd/luks.rst b/doc/usage/cmd/luks.rst index b88fcd96439..c3b03eeff2e 100644 --- a/doc/usage/cmd/luks.rst +++ b/doc/usage/cmd/luks.rst @@ -106,6 +106,35 @@ Display LUKS header information for a LUKS2 partition:: Label: Checksum alg: sha256 + JSON metadata (12288 bytes): + { + "keyslots": { + "0": { + "type": "luks2", + "key_size": 64, + "kdf": { + "type": "argon2id", + "time": 6, + "memory": 1048576, + "cpus": 4, + ... + }, + ... + } + }, + "tokens": {}, + "segments": { + "0": { + "type": "crypt", + "offset": "16777216", + "encryption": "aes-xts-plain64", + ... + } + }, + "digests": { ... }, + "config": { ... } + } + Display LUKS header information for a LUKS1 partition:: => luks info mmc 1:1 diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index b07012ec7c9..34cd2ee8e59 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -278,6 +278,7 @@ config BLK_LUKS select SHA256 select PBKDF2 select PKCS5_MBEDTLS if MBEDTLS_LIB_CRYPTO + select JSON help This provides support for detecting and decrypting LUKS (Linux Unified Key Setup) encrypted partitions. LUKS is a disk encryption specification diff --git a/drivers/block/luks.c b/drivers/block/luks.c index 597359b98ff..c43cb9a3dd3 100644 --- a/drivers/block/luks.c +++ b/drivers/block/luks.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -103,6 +104,28 @@ int luks_show_info(struct udevice *blk, struct disk_partition *pinfo) printf("UUID: %.40s\n", luks2_hdr->uuid); printf("Label: %.48s\n", luks2_hdr->label); printf("Checksum alg: %.32s\n", luks2_hdr->csum_alg); + + if (IS_ENABLED(CONFIG_JSON)) { + u64 json_size; + char *json_start; + int blocks; + + /* Read the full header to get JSON area */ + blocks = (hdr_size + desc->blksz - 1) / desc->blksz; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, full_hdr, blocks * desc->blksz); + + if (blk_read(blk, pinfo->start, blocks, full_hdr) != blocks) { + printf("Error: failed to read full LUKS2 header\n"); + return -EIO; + } + + /* JSON starts after the 4096-byte binary header */ + json_start = (char *)(full_hdr + 4096); + json_size = hdr_size - 4096; + + printf("\nJSON metadata (%llx bytes):\n", json_size); + json_print_pretty(json_start, (int)json_size); + } } else { printf("Unknown LUKS version\n"); return -EPROTONOSUPPORT; diff --git a/test/boot/luks.c b/test/boot/luks.c index fadd3819ffe..70ee0fb0824 100644 --- a/test/boot/luks.c +++ b/test/boot/luks.c @@ -20,19 +20,49 @@ DECLARE_GLOBAL_DATA_PTR; -/* Common function to setup mmc11 device */ -static int setup_mmc11(struct unit_test_state *uts, struct udevice **mmcp) +/** + * setup_mmc_device() - Set up an MMC device for testing + * + * This function binds and probes an MMC device specified by its device tree + * node name. It is used to prepare MMC devices containing test disk images + * with various configurations (e.g., LUKS1, LUKS2 encryption). + * + * @uts: Unit test state + * @node_name: Name of the device tree node (e.g., "mmc11", "mmc12") + * @mmcp: Returns pointer to the MMC device + * Return: 0 if OK, -ve on error + */ +static int setup_mmc_device(struct unit_test_state *uts, const char *node_name, + struct udevice **mmcp) { + struct udevice *mmc; ofnode root, node; - /* Enable the mmc11 node */ + /* Enable the specified mmc node */ root = oftree_root(oftree_default()); - node = ofnode_find_subnode(root, "mmc11"); + node = ofnode_find_subnode(root, node_name); ut_assert(ofnode_valid(node)); - ut_assertok(lists_bind_fdt(gd->dm_root, node, mmcp, NULL, false)); + ut_assertok(lists_bind_fdt(gd->dm_root, node, &mmc, NULL, false)); /* Probe the device */ - ut_assertok(device_probe(*mmcp)); + ut_assertok(device_probe(mmc)); + *mmcp = mmc; + + return 0; +} + +/* Setup mmc11 device */ +static int setup_mmc11(struct unit_test_state *uts, struct udevice **mmcp) +{ + ut_assertok(setup_mmc_device(uts, "mmc11", mmcp)); + + return 0; +} + +/* Setup mmc12 device */ +static int setup_mmc12(struct unit_test_state *uts, struct udevice **mmcp) +{ + ut_assertok(setup_mmc_device(uts, "mmc12", mmcp)); return 0; } @@ -107,3 +137,79 @@ static int bootstd_test_luks_info(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootstd_test_luks_info, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); + +/* Test LUKSv2 detection on mmc12 partitions */ +static int bootstd_test_luks2_detect(struct unit_test_state *uts) +{ + struct disk_partition info; + struct blk_desc *desc; + struct udevice *mmc; + int ret; + + ut_assertok(setup_mmc12(uts, &mmc)); + desc = blk_get_by_device(mmc); + ut_assertnonnull(desc); + ut_assertnonnull(desc->bdev); + + /* Check partition 1 - should NOT be LUKS */ + ut_assertok(part_get_info(desc, 1, &info)); + ret = luks_detect(desc->bdev, &info); + ut_assert(ret < 0); /* Should fail - not LUKS */ + + /* Check partition 2 - should BE LUKS */ + ut_assertok(part_get_info(desc, 2, &info)); + ut_assertok(luks_detect(desc->bdev, &info)); + + /* Verify it's LUKS version 2 */ + ut_asserteq(2, luks_get_version(desc->bdev, &info)); + + return 0; +} +BOOTSTD_TEST(bootstd_test_luks2_detect, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); + +/* Test LUKSv2 command on mmc12 partitions */ +static int bootstd_test_luks2_cmd(struct unit_test_state *uts) +{ + struct udevice *mmc; + + ut_assertok(setup_mmc12(uts, &mmc)); + + /* Test partition 1 - should NOT be LUKS */ + ut_asserteq(1, run_command("luks detect mmc c:1", 0)); + ut_assert_nextlinen("Not a LUKS partition (error -"); + ut_assert_console_end(); + + /* Test partition 2 - should BE LUKS */ + ut_assertok(run_command("luks detect mmc c:2", 0)); + ut_assert_nextline("LUKS2 encrypted partition detected"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootstd_test_luks2_cmd, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); + +/* Test LUKSv2 info command on mmc12 partition 2 */ +static int bootstd_test_luks2_info(struct unit_test_state *uts) +{ + struct udevice *mmc; + + ut_assertok(setup_mmc12(uts, &mmc)); + + /* Test partition 2 LUKS info */ + ut_assertok(run_command("luks info mmc c:2", 0)); + ut_assert_nextline("Version: 2"); + ut_assert_nextlinen("Header size:"); + ut_assert_nextlinen("Sequence ID:"); + ut_assert_nextlinen("UUID:"); + ut_assert_nextlinen("Label:"); + ut_assert_nextlinen("Checksum alg:"); + + /* Verify JSON metadata section is present (skip empty line first) */ + ut_assert_skip_to_line(""); + ut_assert_nextlinen("JSON metadata ("); + ut_assert_nextline("{"); + /* JSON output varies and there is little value in checking it here */ + + return 0; +} +BOOTSTD_TEST(bootstd_test_luks2_info, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);