@@ -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
@@ -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
@@ -8,6 +8,7 @@
#include <blk.h>
#include <dm.h>
#include <hexdump.h>
+#include <json.h>
#include <log.h>
#include <luks.h>
#include <memalign.h>
@@ -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;
@@ -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);