From patchwork Wed Nov 12 12:42:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 687 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951393; bh=b4kNn13JnZRCYtWUG7E+NyOLQ1kcgTUYkSbPPpBVv3c=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=Tms0c/FdM1jgQP5p7v85K+HxM/hPJBuBEY71mkemZoZGSaX68JXDz64vBbI7L4KW+ 2uOVzPCvdxOuSGRjNZMBggbTsfdPd/DoYzwjBi5hqfM5chHMVQ7MWApFDGwJEbwLpS qRu5WAoWX5yHZq7nGlTVNtWkWt2sbO8e5B0vadsaPwHWmslf2XfHQolyEv94//eEhS 3qZbx0nAa0YeS78oiIXtq+N4Kbh6KkB10PHRKFOYirrt8ipqnORlaUo2mbMs6u1ln/ s959biSVGgFGcODOj/pqSXWTkXC+wUsOuXYryZjxfRCHXdjuI/sE6vL8Xo+bz9pgbb CiBtbQ0gHaqgA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 0F010684F6 for ; Wed, 12 Nov 2025 05:43:13 -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 TrQ1TWvC-Wy1 for ; Wed, 12 Nov 2025 05:43:13 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951392; bh=b4kNn13JnZRCYtWUG7E+NyOLQ1kcgTUYkSbPPpBVv3c=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=MUMLcgYhvFHmSi5imGuY+YOrm1phz06CZezOzwTadLf5HUmH8Fg0Mpe0zS0v3JO09 DQhMz16qSp7jPaaRZm/avXEBJ5wRqJ6fPTNlo/ng0FLykKLyCMah63qvF3OWpl+EZF 1NN41cBiLR4DJgmQaE2bd7Om2uWxldLcK4BZo09aefMnd8izswbRWMS1yj/Lv4mbqo R67AXH3wjTsUdIJhUimAOebr07BIxM1zvBqvpKCKAvHAH7xpQEAJ9SE+lqoEDFmMmK ErY4MKfW9mvham3T1AaSB/FU7JX1oaF5WpD5hKTisLjY1ZfFqmXMYtLMhAxKgDgQ5j JYoYtVbS7+xtQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id F3AD7683FC for ; Wed, 12 Nov 2025 05:43:12 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951390; bh=Z+KmQRAeFDElhmg4Ox1SjvM+a1VOq93W0y2epBHc59Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=b5qgKjw1splGD7H7hpUeBx30PnboR/JAgiIfEzUero0OKrGizbhnjb0k/NKvC61k0 xA9xVnAN0ZZS55zVRPqPTytTem8vOkblhkET4lE7i9OYzbqFeWZFBiNM75qYt/C9L3 bBRjMCTr9GwAAEX/X93dXHvmY64RoGINo3oAxp/EKPYVwTcW1PiCaaGnac/AGJ8yWt cJlS6GIbgPYkKJ9DNn5j7yvV/2HYUgIfSCKimcf66YmtFRAeEamjoBkxfrHiPcszVb 9u/ajfh5WOBW4TJNA3rk0HFn4q5OAA185fepSl0pw2GwVjw1NN1tST2hpO7ejksdJX sWGdJfO8jOCFg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id DCD23682E4; Wed, 12 Nov 2025 05:43:10 -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 10026) with ESMTP id Z6OWPpUv9plP; Wed, 12 Nov 2025 05:43:10 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951386; bh=dz3Xf8oZauQVT55hd0yWi2dP+XVm2WCTNzWsHcwhtRU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RULjyqBhXsy85RHhc0S0CYwjVSWN1N3xGtNL098FhiotqkrOsL00r+Rtcwo1efz3q 9Rpp9gerWal6nRXZXflGV4G7VF5kFalXIt7wHFwqrM6Ea9F/6y77WTiEsR4b8o4EDb TaxPfSuWox7rTSbTSxxrnrGVaDOu3aCOemXUvFPcfrEUhyyNremjqMlVBN1oI1OA5v VIymk/t2hyQ7ynZyIzg1BurIC2mYX3ISUD2/i7NbJm8wL+FZWsJLpZ4sdd5YpWsWAi BnN39pvvFxy3BxRsA3QJGU4tT77WGdDI1M7l3O+BCrcjc6L47kKGczPOAunRbzjMLU 57JWbA+cljXhw== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 8DD9E68375; Wed, 12 Nov 2025 05:43:06 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Wed, 12 Nov 2025 05:42:42 -0700 Message-ID: <20251112124252.1081477-2-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251112124252.1081477-1-sjg@u-boot.org> References: <20251112124252.1081477-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: JUB5EJIVEPYGFQ2NJZHECN5Q6Z2MFR2Q X-Message-ID-Hash: JUB5EJIVEPYGFQ2NJZHECN5Q6Z2MFR2Q X-MailFrom: sjg@u-boot.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 1/5] luks: Exclude the payload from the size calculation List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Fix the blkmap-size calculation to exclude the LUKS header/payload offset. This was missed in the initial implementation. Co-developed-by: Claude Signed-off-by: Simon Glass Fixes: 0cbfb2d4900 ("luks: Provide a way to unlock and map encrypted..") --- drivers/block/luks.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/block/luks.c b/drivers/block/luks.c index 3bdfd7dba61..c7e5a3da154 100644 --- a/drivers/block/luks.c +++ b/drivers/block/luks.c @@ -596,6 +596,7 @@ int luks_create_blkmap(struct udevice *blk, struct disk_partition *pinfo, struct udevice **blkmapp) { u8 essiv_key[SHA256_SUM_LEN]; /* SHA-256 output */ + lbaint_t decrypted_size; struct luks1_phdr *hdr; struct luks2_hdr *hdr2; struct blk_desc *desc; @@ -736,10 +737,15 @@ int luks_create_blkmap(struct udevice *blk, struct disk_partition *pinfo, } } - /* Map the encrypted partition to the blkmap device */ - log_debug("mapping blkmap: blknr 0 blkcnt %lx payload_offset %x essiv %d\n", - (ulong)pinfo->size, payload_offset, use_essiv); - ret = blkmap_map_crypt(dev, 0, pinfo->size, blk, pinfo->start, + /* + * Map the encrypted partition to the blkmap device. The decrypted size + * is the partition size minus the payload offset + */ + decrypted_size = pinfo->size - payload_offset; + log_debug("mapping blkmap: blknr 0 blkcnt %llx payload_offset %x essiv %d\n", + (unsigned long long)decrypted_size, payload_offset, + use_essiv); + ret = blkmap_map_crypt(dev, 0, decrypted_size, blk, pinfo->start, master_key, key_size, payload_offset, use_essiv, use_essiv ? essiv_key : NULL); if (ret) { From patchwork Wed Nov 12 12:42:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 688 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951395; bh=piGvgppAO+h7Ht1u1pvFi3mSeZEKbA8QbwP3g0U6NxM=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=qvRSz0dr8kRXzQ8BCXNSBWwvb1i+t51dgEdfAb4moZ2enuuSE5R9GFL8FPodE7Dsx GZ7WZPQ1SHuIBBAsQjzPo6k1z9Rlo5lBevi+bzxudar0yUraejgnvDulJCJmsFYQDn pmyCkugITK602ESiWUjEhaWPL+ZG6raDYhvGTFICvcudoRfypEWAzRSklfkn/ajsgP hOvVQtKts9j8YJUJZ1tvm/VIJKi9/VqeLblbsnbtCFWcnmKfpLQYg1ZJFU9cewNjSC fpYx1OhuChsF+Bwu8q24XsRl53aHa/SVh59fZ+nYIQPoBVb5ze7WnIKbhDjtQjeWns P31pyzYFQ7Q8w== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 7ACC2682E4 for ; Wed, 12 Nov 2025 05:43:15 -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 PuoBabPbCnDw for ; Wed, 12 Nov 2025 05:43:15 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951394; bh=piGvgppAO+h7Ht1u1pvFi3mSeZEKbA8QbwP3g0U6NxM=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=sGKL0xhEqHzCsrQSL83SlIpY1VBJwShTRSW9KMOT0NdI8GjxgvCSwUK2AEWbMS6/H 9X+wSvqDjwGk7RO06gtrsIuGTs0JyWUuLDxR3G1eLqNLG7NEXTrGIQ94T315Coaa2+ +9Gx0fWDJ6JeAOuZOTX0hmdRWMDOrcWt3jFNAYNHqorbJWG1bN8o8spbI4j5vE3DOI jZM9a1SgeHzJBSDklXLkAuopf69gpxV4gcfZWGFC2StB/L6mDRvxdZdAkT5hiG5GbA DuUfoftXGc1bALmNcCrkOqsTdF/k3I9qWtUXaBoVDC3Fw60cxV4bnrD7jfGk/r3ajh eg5jOgigs0IGg== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 6AFDD683FC for ; Wed, 12 Nov 2025 05:43:14 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951391; bh=i5hZMmUYGwmWnjv/EneJ+T7vAqSgW/l+o2vu/NxfLAE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XBRLPMVmg96sMuiXFjUwsVyKM473c0ooInGgH6zzQxthur7mDwh2o170k4S+Ax3Fx IVGjTOf3EVkMqmR7IMNq/CX0Rem/SlotGMOU9+brxTqaVas7i9AywmLmknf3QX3GGL J1fbYsinGHPsZg09GwAhJHJVLCcSIbBp9CN2UHecGw6M7s4kJEDGcXcWNeT4Pm99mk buQ9/CTwfjFAiif/5R+uEyWcbt8sN2j5P5ySd5CkKoNu6BILTaztoJOv7JeRZEHsFj ovCK3s9PZdI73Vh9p4Cvu5QJtNGAGn/nNtnRm3zxqyv2XSx6FeAK0GbUz7TMLZk9LW MdsMagskRi92w== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id BABC6682E4; Wed, 12 Nov 2025 05:43:11 -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 10026) with ESMTP id EAVa7_LGVNxm; Wed, 12 Nov 2025 05:43:11 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951391; bh=hEd+2hOQIdHLBqpiHiQPdDRSBBkVhpJIaD81XK+/V+A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=e3iuVWt+E0Tk5L9wTMDoghe/fzvAZrOekF9fqfBBycJGgjCjoJtqHSx9UK68/V8+/ +cRkC3TtgeAoQfAYXJblLdESJpXUTHSJ4M2D+ma9YluABxeQWnPWHtGlYoySzDUoeS kG+mZY4PMGr10OwRqO6J00/n8QkYoeCrvuXTcbxhtiwOihGZNi6qHcoz5FOKQBJv8M o8bXLSoBHgcNsGCaiLez8+w1iwez8dn5bSRzPtt0LIb/+ShczAtFXQbTh6CRuuR2T9 ieij2ZZeuH0U84NWb4MgTK7TadIefCRcunoiXVhGR6/0ZF5+x/FL46oBWVB+C2HwSC ElYwVzgyrck/A== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 268B868375; Wed, 12 Nov 2025 05:43:11 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Wed, 12 Nov 2025 05:42:43 -0700 Message-ID: <20251112124252.1081477-3-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251112124252.1081477-1-sjg@u-boot.org> References: <20251112124252.1081477-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: C56PFEUT5FHA7J24N62WJQG2FD5VQIY5 X-Message-ID-Hash: C56PFEUT5FHA7J24N62WJQG2FD5VQIY5 X-MailFrom: sjg@u-boot.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 2/5] luks: test: Check file access in the decryption tests List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass The current tests check that decryption happens but don't go so far as reading a file. Add the logic for this. Since this currently fails for LUKSv2, leave the last part of that test out for now. Use direct filesystem calls for LUKSv2 since it is easier to check for the current error. Add more information on the errors returned by luks_unlock() so we can check for the correct one. Co-developed-by: Claude Signed-off-by: Simon Glass --- include/luks.h | 8 +++++++- test/boot/luks.c | 44 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/include/luks.h b/include/luks.h index 2c52cc48689..4f65f3029f8 100644 --- a/include/luks.h +++ b/include/luks.h @@ -148,7 +148,13 @@ int luks_show_info(struct udevice *blk, struct disk_partition *pinfo); * @pass: Passphrase to unlock the partition * @master_key: Buffer to receive the decrypted master key * @key_size: Size of the master_key buffer - * Return: 0 on success, -ve on error + * Return: 0 on success, + * -EINVAL if null parameters, + * -EACCES if passphrase is incorrect, + * -ENOENT if not a LUKS partition or no active key slots, + * -ENOTSUPP if unsupported version/cipher/hash, + * -ENOMEM if memory allocation failed, + * -EIO if failed to read from block device */ int luks_unlock(struct udevice *blk, struct disk_partition *pinfo, const char *pass, u8 *master_key, u32 *key_size); diff --git a/test/boot/luks.c b/test/boot/luks.c index 4ee6081a790..ec95b241d8a 100644 --- a/test/boot/luks.c +++ b/test/boot/luks.c @@ -7,6 +7,8 @@ #include #include +#include +#include #include #include #include @@ -217,7 +219,9 @@ BOOTSTD_TEST(bootstd_test_luks2_info, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); /* Test LUKS unlock command with LUKS1 encrypted partition */ static int bootstd_test_luks_unlock(struct unit_test_state *uts) { + struct blk_desc *desc; struct udevice *mmc; + loff_t file_size; ut_assertok(setup_mmc11(uts, &mmc)); @@ -233,6 +237,18 @@ static int bootstd_test_luks_unlock(struct unit_test_state *uts) ut_assert_nextline("Unlocked LUKS partition as blkmap device 'luks-mmc-b:2'"); ut_assert_console_end(); + /* Get the blkmap device number */ + ut_assertok(run_command("blkmap get luks-mmc-b:2 dev devnum", 0)); + ut_assert_console_end(); + + /* Verify that a file can be read from the decrypted filesystem */ + desc = blk_get_devnum_by_uclass_idname("blkmap", 0); + ut_assertnonnull(desc); + + ut_assertok(fs_set_blk_dev_with_part(desc, 0)); + ut_assertok(fs_size("/bin/bash", &file_size)); + ut_asserteq(5, file_size); + /* Test unlocking with wrong passphrase */ ut_asserteq(1, run_command("luks unlock mmc b:2 wrongpass", 0)); ut_assert_skip_to_line("Failed to unlock LUKS partition (err -13: Permission denied)"); @@ -244,15 +260,22 @@ BOOTSTD_TEST(bootstd_test_luks_unlock, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); /* Test LUKS2 unlock command with LUKS2 encrypted partition */ static int bootstd_test_luks2_unlock(struct unit_test_state *uts) { + struct disk_partition info; + struct blk_desc *desc; struct udevice *mmc; + u8 master_key[512]; + loff_t file_size; + u32 key_size; ut_assertok(setup_mmc12(uts, &mmc)); + desc = blk_get_by_device(mmc); + ut_assertnonnull(desc); + ut_assertnonnull(desc->bdev); - /* Test that unlock command exists and handles errors properly */ - /* Should fail because partition 1 is not LUKS */ - ut_asserteq(1, run_command("luks unlock mmc c:1 test", 0)); - ut_assert_nextline("Not a LUKS partition"); - ut_assert_console_end(); + /* Test that unlock fails for partition 1 (not LUKS) */ + ut_assertok(part_get_info(desc, 1, &info)); + ut_asserteq(-ENOENT, luks_unlock(desc->bdev, &info, "test", master_key, + &key_size)); /* Test unlocking partition 2 with correct passphrase */ ut_assertok(run_command("luks unlock mmc c:2 test", 0)); @@ -260,6 +283,17 @@ static int bootstd_test_luks2_unlock(struct unit_test_state *uts) ut_assert_nextline("Unlocked LUKS partition as blkmap device 'luks-mmc-c:2'"); ut_assert_console_end(); + /* Verify that a file can be read from the decrypted filesystem */ + desc = blk_get_devnum_by_uclass_idname("blkmap", 0); + ut_assertnonnull(desc); + + /* at present this fails due to incorrect decryption */ + if (0) { + ut_assertok(fs_set_blk_dev_with_part(desc, 0)); + ut_assertok(fs_size("/bin/bash", &file_size)); + ut_asserteq(5, file_size); + } + /* Test unlocking with wrong passphrase */ ut_asserteq(1, run_command("luks unlock mmc c:2 wrongpass", 0)); ut_assert_nextline("Unlocking LUKS2 partition..."); From patchwork Wed Nov 12 12:42:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 689 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951399; bh=fkgUeCqR7HXayJQehXIGsh62A7oKI1paZhl5Ts/avU8=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=V4qLyap/XLKeVfuAacHQYmF/Lijwt9Nz4t6sVVeoi0t4Msx/91wexrYwSsgDhqwy6 FhLL9wP1YP+Ts5Z6PP3iYFNeHfkD54lOCtZLU5HvCCTMD6i65TvHPZHDn9gCF6rQbn QuS+0i8Mi6IbS8qIhCz+AOn0flw5D40dWIMOIJiqDvHxrwqrRP9AhK/ZokXsUEH2uO KM9DBLtUcvq3blDg/zQfLmH4FQbwUkMoY2rtITEi8DzdxIanXfXhNf7g1FNbHHhF6i ZPwa5PeLVPylqTUrX5wTpuQzNfvq8gg4X1mn0cLpaObTKHjC4L+uNZIZ8O566eLzrQ DhQPr4qypJRkw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 4A9AF684F6 for ; Wed, 12 Nov 2025 05:43:19 -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 YOZHFA38qzGJ for ; Wed, 12 Nov 2025 05:43:19 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951399; bh=fkgUeCqR7HXayJQehXIGsh62A7oKI1paZhl5Ts/avU8=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=V4qLyap/XLKeVfuAacHQYmF/Lijwt9Nz4t6sVVeoi0t4Msx/91wexrYwSsgDhqwy6 FhLL9wP1YP+Ts5Z6PP3iYFNeHfkD54lOCtZLU5HvCCTMD6i65TvHPZHDn9gCF6rQbn QuS+0i8Mi6IbS8qIhCz+AOn0flw5D40dWIMOIJiqDvHxrwqrRP9AhK/ZokXsUEH2uO KM9DBLtUcvq3blDg/zQfLmH4FQbwUkMoY2rtITEi8DzdxIanXfXhNf7g1FNbHHhF6i ZPwa5PeLVPylqTUrX5wTpuQzNfvq8gg4X1mn0cLpaObTKHjC4L+uNZIZ8O566eLzrQ DhQPr4qypJRkw== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 38E71683FC for ; Wed, 12 Nov 2025 05:43:19 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951397; bh=APQO1WGmV24aUIoxBYNQry/I3IT1EwwktBzhsTBnBS8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eL8BOD6zYfSr5CyYqF0+3rVmpu2YyabJm8BuNX0yE3xZSWBfzG4W9ZSCwdAdKjXOw UnBVOBrPX3mttdnLyioBnqV6tpYQVRy0i/qRi5yQ7plyHPiRcld1R5JWQIlL5AGjrx pYfbkWJ1ON5F28eCdOmnieBCjKCf6ZuhJoexQwVoZq3/adeQHdZDlSsLXcVMOcS2JU slFJHiDwLoqas98vk+6e9ttzSETbstPtetceO972NKQIiMNx3x6XcxLw1lghszgMkB Cnz9BJQhXsKBiqU41ApPCnaUULYWwrwFndI2eKhW527MGwvsc/R7prPybVYBIqIUaX V0DhU4AV2A7Gg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id D130A683FC; Wed, 12 Nov 2025 05:43:17 -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 10026) with ESMTP id bNCuwkZioG98; Wed, 12 Nov 2025 05:43:17 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951392; bh=/j/Quqz4h0hGTtfXOs70cfHtSLVeu9bvv00ZLrOAsUQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=prxYSlrDGZC7FB+wwMQ9BJvRg4sCq6Jz0yWZzWmCE9dV+d8970fjbHtTeR56VDEde QFrk5fy9VUzACgCD6vgtKfgFkF1In4JSICWdDbt3d8Yf5VQuyTGUinHy0MbW8kdmq2 fQ4jQAe2JZo/gD64byVPpDWrHNtSoOm7db+6zzmqRkkXhEbw7kp9wyPI6QjpymQg9F aPtZUOKHcCeyYkACqkUQLYDCCTZ39G9j5f7SDz+dnFYGtn2PYqltShEkEc3s+CtrtO pMA0+/jtN6YLyr2GuV13xbLiKqi1ENe0wfh1as0y7I35/ziZt7epcJzU1io4bjWoDw qAxNGBWtsEE3Q== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 0AF7568375; Wed, 12 Nov 2025 05:43:11 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Wed, 12 Nov 2025 05:42:44 -0700 Message-ID: <20251112124252.1081477-4-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251112124252.1081477-1-sjg@u-boot.org> References: <20251112124252.1081477-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 45ZU6VZ7VQIPBWJ6NBDV7ILKFPTIG4YE X-Message-ID-Hash: 45ZU6VZ7VQIPBWJ6NBDV7ILKFPTIG4YE X-MailFrom: sjg@u-boot.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 X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 3/5] luks: Move blkmap crypt code into a separate file List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Create a new blkmap_crypt.c file to hold the LUKS code, since it is fairly large. Add an internal header for blkmap as well. Signed-off-by: Simon Glass --- drivers/block/Makefile | 1 + drivers/block/blkmap.c | 204 +------------------------------- drivers/block/blkmap_crypt.c | 172 +++++++++++++++++++++++++++ drivers/block/blkmap_internal.h | 74 ++++++++++++ 4 files changed, 249 insertions(+), 202 deletions(-) create mode 100644 drivers/block/blkmap_crypt.c create mode 100644 drivers/block/blkmap_internal.h diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 538b602790d..0735efea719 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -17,6 +17,7 @@ endif obj-$(CONFIG_SANDBOX) += sandbox.o host-uclass.o host_dev.o obj-$(CONFIG_$(PHASE_)BLOCK_CACHE) += blkcache.o obj-$(CONFIG_$(PHASE_)BLKMAP) += blkmap.o +obj-$(CONFIG_BLK_LUKS) += blkmap_crypt.o obj-$(CONFIG_$(PHASE_)BLKMAP) += blkmap_helper.o obj-$(CONFIG_EFI_MEDIA) += efi-media-uclass.o diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c index 13a79001979..14aa1e4d088 100644 --- a/drivers/block/blkmap.c +++ b/drivers/block/blkmap.c @@ -11,62 +11,11 @@ #include #include #include -#include #include #include #include #include - -struct blkmap; - -/** - * struct blkmap_slice - Region mapped to a blkmap - * - * Common data for a region mapped to a blkmap, specialized by each - * map type. - * - * @node: List node used to associate this slice with a blkmap - * @blknr: Start block number of the mapping - * @blkcnt: Number of blocks covered by this mapping - */ -struct blkmap_slice { - struct list_head node; - - lbaint_t blknr; - lbaint_t blkcnt; - - /** - * @read: - Read from slice - * - * @read.bm: Blkmap to which this slice belongs - * @read.bms: This slice - * @read.blknr: Start block number to read from - * @read.blkcnt: Number of blocks to read - * @read.buffer: Buffer to store read data to - */ - ulong (*read)(struct blkmap *bm, struct blkmap_slice *bms, - lbaint_t blknr, lbaint_t blkcnt, void *buffer); - - /** - * @write: - Write to slice - * - * @write.bm: Blkmap to which this slice belongs - * @write.bms: This slice - * @write.blknr: Start block number to write to - * @write.blkcnt: Number of blocks to write - * @write.buffer: Data to be written - */ - ulong (*write)(struct blkmap *bm, struct blkmap_slice *bms, - lbaint_t blknr, lbaint_t blkcnt, const void *buffer); - - /** - * @destroy: - Tear down slice - * - * @read.bm: Blkmap to which this slice belongs - * @read.bms: This slice - */ - void (*destroy)(struct blkmap *bm, struct blkmap_slice *bms); -}; +#include "blkmap_internal.h" static bool blkmap_slice_contains(struct blkmap_slice *bms, lbaint_t blknr) { @@ -92,7 +41,7 @@ static bool blkmap_slice_available(struct blkmap *bm, struct blkmap_slice *new) return true; } -static int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new) +int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new) { struct blk_desc *bd = dev_get_uclass_plat(bm->blk); struct list_head *insert = &bm->slices; @@ -293,155 +242,6 @@ int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, return err; } -/** - * struct blkmap_crypt - Encrypted device mapping - * - * @slice: Common map data - * @blk: Target encrypted block device - * @blknr: Start block number of encrypted data on target device - * @master_key: Decrypted master key for this mapping - * @key_size: Size of master key in bytes - * @payload_offset: LUKS payload offset in sectors - * @use_essiv: True if ESSIV mode is used for IV generation - * @essiv_key: ESSIV key (SHA256 hash of master key) - */ -struct blkmap_crypt { - struct blkmap_slice slice; - struct udevice *blk; - lbaint_t blknr; - u8 master_key[128]; - u32 key_size; - u32 payload_offset; - bool use_essiv; - u8 essiv_key[32]; -}; - -static ulong blkmap_crypt_read(struct blkmap *bm, struct blkmap_slice *bms, - lbaint_t blknr, lbaint_t blkcnt, void *buffer) -{ - struct blkmap_crypt *bmc = container_of(bms, struct blkmap_crypt, slice); - struct blk_desc *bd = dev_get_uclass_plat(bm->blk); - struct blk_desc *src_bd = dev_get_uclass_plat(bmc->blk); - lbaint_t src_blknr, blocks_read; - u8 *encrypted_buf, *dest = buffer; - u8 expkey[AES256_EXPAND_KEY_LENGTH]; - u8 iv[AES_BLOCK_LENGTH]; - u64 sector; - lbaint_t i; - - /* Allocate buffer for encrypted data */ - encrypted_buf = malloc_cache_aligned(blkcnt * src_bd->blksz); - if (!encrypted_buf) - return 0; - - /* - * Calculate source block number (LUKS payload offset + requested - * block) - */ - src_blknr = bmc->blknr + bmc->payload_offset + blknr; - - /* Read encrypted data from underlying device */ - blocks_read = blk_read(bmc->blk, src_blknr, blkcnt, encrypted_buf); - if (blocks_read != blkcnt) { - free(encrypted_buf); - return 0; - } - - /* Expand AES key */ - aes_expand_key(bmc->master_key, bmc->key_size * 8, expkey); - - /* Decrypt each sector */ - for (i = 0; i < blkcnt; i++) { - /* Calculate sector number for IV */ - sector = blknr + i; - - if (bmc->use_essiv) { - /* - * ESSIV mode: - * IV = AES_encrypt(sector_number, SHA256(master_key)) - */ - u8 essiv_expkey[AES256_EXPAND_KEY_LENGTH]; - u8 sector_iv[AES_BLOCK_LENGTH]; - - /* Create sector number as IV input (little-endian) */ - memset(sector_iv, 0, sizeof(sector_iv)); - *(u64 *)sector_iv = cpu_to_le64(sector); - - /* Expand ESSIV key */ - aes_expand_key(bmc->essiv_key, 256, essiv_expkey); - - /* Encrypt sector number with ESSIV key to get IV */ - aes_encrypt(256, sector_iv, essiv_expkey, iv); - } else { - /* - * Plain64 mode: - * IV is sector number in little-endian format - */ - memset(iv, '\0', sizeof(iv)); - *(u64 *)iv = cpu_to_le64(sector); - } - - /* Decrypt sector using AES-CBC */ - aes_cbc_decrypt_blocks(bmc->key_size * 8, expkey, iv, - encrypted_buf + i * bd->blksz, - dest + i * bd->blksz, - bd->blksz / AES_BLOCK_LENGTH); - } - free(encrypted_buf); - - return blkcnt; -} - -static void blkmap_crypt_destroy(struct blkmap *bm, struct blkmap_slice *bms) -{ - struct blkmap_crypt *bmc = container_of(bms, struct blkmap_crypt, slice); - - /* Securely wipe master key before freeing */ - memset(bmc->master_key, 0, sizeof(bmc->master_key)); - free(bmc); -} - -int blkmap_map_crypt(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, - struct udevice *lblk, lbaint_t lblknr, - const u8 *master_key, u32 key_size, u32 payload_offset, - bool use_essiv, const u8 *essiv_key) -{ - struct blkmap *bm = dev_get_plat(dev); - struct blkmap_crypt *bmc; - int err; - - if (key_size > 128) - return -EINVAL; - - bmc = malloc(sizeof(*bmc)); - if (!bmc) - return -ENOMEM; - - bmc->blk = lblk; - bmc->blknr = lblknr; - bmc->key_size = key_size; - bmc->payload_offset = payload_offset; - bmc->use_essiv = use_essiv; - memcpy(bmc->master_key, master_key, key_size); - - if (use_essiv && essiv_key) - memcpy(bmc->essiv_key, essiv_key, sizeof(bmc->essiv_key)); - else - memset(bmc->essiv_key, 0, sizeof(bmc->essiv_key)); - - bmc->slice.blknr = blknr; - bmc->slice.blkcnt = blkcnt; - bmc->slice.read = blkmap_crypt_read; - bmc->slice.write = NULL; /* Read-only for now */ - bmc->slice.destroy = blkmap_crypt_destroy; - - err = blkmap_slice_add(bm, &bmc->slice); - if (err) - free(bmc); - - return err; -} - static ulong blkmap_blk_read_slice(struct blkmap *bm, struct blkmap_slice *bms, lbaint_t blknr, lbaint_t blkcnt, void *buffer) diff --git a/drivers/block/blkmap_crypt.c b/drivers/block/blkmap_crypt.c new file mode 100644 index 00000000000..bc77ddc2751 --- /dev/null +++ b/drivers/block/blkmap_crypt.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2025 Canonical Ltd + * Author: Simon Glass + * + * LUKS encryption/decryption support + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "blkmap_internal.h" + +/** + * struct blkmap_crypt - Encrypted mapping + * + * Data associated with an encrypted region of a block device (e.g., LUKS). + * Provides on-the-fly decryption of data using AES-CBC or AES-XTS modes. + * + * @slice: Common slice data (must be first member) + * @blk: Underlying block device containing encrypted data + * @blknr: Start block of the underlying block device + * @master_key: Decrypted master key for decryption + * @key_size: Size of the master key in bytes (must be <= 128) + * @payload_offset: Offset in sectors from lblknr to actual encrypted payload + * @sector_size: Sector size for IV calculation (typically 512 or 4096) + * @use_essiv: True if ESSIV mode is used for IV generation (CBC only) + * @essiv_key: ESSIV key (SHA256 hash of master key) + */ +struct blkmap_crypt { + struct blkmap_slice slice; + struct udevice *blk; + lbaint_t blknr; + u8 master_key[128]; + u32 key_size; + u32 payload_offset; + u32 sector_size; + bool use_essiv; + u8 essiv_key[32]; +}; + +static ulong blkmap_crypt_read(struct blkmap *bm, struct blkmap_slice *bms, + lbaint_t blknr, lbaint_t blkcnt, void *buffer) +{ + struct blkmap_crypt *bmc = container_of(bms, struct blkmap_crypt, slice); + struct blk_desc *bd = dev_get_uclass_plat(bm->blk); + struct blk_desc *src_bd = dev_get_uclass_plat(bmc->blk); + lbaint_t src_blknr, blocks_read; + u8 *encrypted_buf, *dest = buffer; + u8 expkey[AES256_EXPAND_KEY_LENGTH]; + u8 iv[AES_BLOCK_LENGTH]; + u64 sector; + lbaint_t i; + + /* Allocate buffer for encrypted data */ + encrypted_buf = malloc_cache_aligned(blkcnt * src_bd->blksz); + if (!encrypted_buf) + return 0; + + /* + * Calculate source block number (LUKS payload offset + requested + * block) + */ + src_blknr = bmc->blknr + bmc->payload_offset + blknr; + + /* Read encrypted data from underlying device */ + blocks_read = blk_read(bmc->blk, src_blknr, blkcnt, encrypted_buf); + if (blocks_read != blkcnt) { + free(encrypted_buf); + return 0; + } + + /* Expand AES key */ + aes_expand_key(bmc->master_key, bmc->key_size * 8, expkey); + + /* Decrypt each sector */ + for (i = 0; i < blkcnt; i++) { + /* Calculate sector number for IV */ + sector = blknr + i; + + if (bmc->use_essiv) { + /* + * ESSIV mode: + * IV = AES_encrypt(sector_number, SHA256(master_key)) + */ + u8 essiv_expkey[AES256_EXPAND_KEY_LENGTH]; + u8 sector_iv[AES_BLOCK_LENGTH]; + + /* Create sector number as IV input (little-endian) */ + memset(sector_iv, '\0', sizeof(sector_iv)); + *(u64 *)sector_iv = cpu_to_le64(sector); + + /* Expand ESSIV key */ + aes_expand_key(bmc->essiv_key, 256, essiv_expkey); + + /* Encrypt sector number with ESSIV key to get IV */ + aes_encrypt(256, sector_iv, essiv_expkey, iv); + } else { + /* + * Plain64 mode: + * IV is sector number in little-endian format + */ + memset(iv, '\0', sizeof(iv)); + *(u64 *)iv = cpu_to_le64(sector); + } + + /* Decrypt sector using AES-CBC */ + aes_cbc_decrypt_blocks(bmc->key_size * 8, expkey, iv, + encrypted_buf + i * bd->blksz, + dest + i * bd->blksz, + bd->blksz / AES_BLOCK_LENGTH); + } + free(encrypted_buf); + + return blkcnt; +} + +static void blkmap_crypt_destroy(struct blkmap *bm, struct blkmap_slice *bms) +{ + struct blkmap_crypt *bmc = container_of(bms, struct blkmap_crypt, slice); + + /* Securely wipe master key before freeing */ + memset(bmc->master_key, '\0', sizeof(bmc->master_key)); + free(bmc); +} + +int blkmap_map_crypt(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + struct udevice *lblk, lbaint_t lblknr, + const u8 *master_key, u32 key_size, u32 payload_offset, + bool use_essiv, const u8 *essiv_key) +{ + struct blkmap *bm = dev_get_plat(dev); + struct blkmap_crypt *bmc; + int err; + + if (key_size > 128) + return -EINVAL; + + bmc = malloc(sizeof(*bmc)); + if (!bmc) + return -ENOMEM; + + bmc->blk = lblk; + bmc->blknr = lblknr; + bmc->key_size = key_size; + bmc->payload_offset = payload_offset; + bmc->use_essiv = use_essiv; + memcpy(bmc->master_key, master_key, key_size); + + if (use_essiv && essiv_key) + memcpy(bmc->essiv_key, essiv_key, sizeof(bmc->essiv_key)); + else + memset(bmc->essiv_key, '\0', sizeof(bmc->essiv_key)); + + bmc->slice.blknr = blknr; + bmc->slice.blkcnt = blkcnt; + bmc->slice.read = blkmap_crypt_read; + bmc->slice.write = NULL; /* Read-only for now */ + bmc->slice.destroy = blkmap_crypt_destroy; + + err = blkmap_slice_add(bm, &bmc->slice); + if (err) + free(bmc); + + return err; +} diff --git a/drivers/block/blkmap_internal.h b/drivers/block/blkmap_internal.h new file mode 100644 index 00000000000..07947c7ef0b --- /dev/null +++ b/drivers/block/blkmap_internal.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2023 Addiva Elektronik + * Author: Tobias Waldekranz + * + * Internal blkmap structures and functions + */ + +#ifndef _BLKMAP_INTERNAL_H +#define _BLKMAP_INTERNAL_H + +#include + +struct blkmap; + +/** + * struct blkmap_slice - Region mapped to a blkmap + * + * Common data for a region mapped to a blkmap, specialized by each + * map type. + * + * @node: List node used to associate this slice with a blkmap + * @blknr: Start block number of the mapping + * @blkcnt: Number of blocks covered by this mapping + */ +struct blkmap_slice { + struct list_head node; + + lbaint_t blknr; + lbaint_t blkcnt; + + /** + * @read: - Read from slice + * + * @read.bm: Blkmap to which this slice belongs + * @read.bms: This slice + * @read.blknr: Start block number to read from + * @read.blkcnt: Number of blocks to read + * @read.buffer: Buffer to store read data to + */ + ulong (*read)(struct blkmap *bm, struct blkmap_slice *bms, + lbaint_t blknr, lbaint_t blkcnt, void *buffer); + + /** + * @write: - Write to slice + * + * @write.bm: Blkmap to which this slice belongs + * @write.bms: This slice + * @write.blknr: Start block number to write to + * @write.blkcnt: Number of blocks to write + * @write.buffer: Data to be written + */ + ulong (*write)(struct blkmap *bm, struct blkmap_slice *bms, + lbaint_t blknr, lbaint_t blkcnt, const void *buffer); + + /** + * @destroy: - Tear down slice + * + * @read.bm: Blkmap to which this slice belongs + * @read.bms: This slice + */ + void (*destroy)(struct blkmap *bm, struct blkmap_slice *bms); +}; + +/** + * blkmap_slice_add() - Add a slice to a blkmap + * + * @bm: Blkmap to add the slice to + * @new: New slice to add + * Returns: 0 on success, negative error code on failure + */ +int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new); + +#endif /* _BLKMAP_INTERNAL_H */ From patchwork Wed Nov 12 12:42:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 690 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951403; bh=Jd38FUsJzdJrKAcO4IA07t37KMFpp1YSxYilE+UykJY=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=poG42Hc1KFcgEyE+vqeIuHo2NxCEVPEtOMhxt6sGcn1y140nj6nKhXZpFKSkV8hD8 cWOB1pCq4GCU6jzGn3T2hbO4Ag6KJ65ldb/ykYOmld+8ksm3oRMK4dFm0u9I/u85pz 18qp2xlKlqeVsipaZSo6uiGmQ0FGie/uxyfaRKEPF4+Qj/yLeyJ+SXpxwIad3bW8wE jI0x0RPiY8zeYQ1vwgZeUQIyMUnzAmM1hQoFAz3lNJeiddFNhz7exCZ0jF9+LPF5pE uZxX27oUBafMfN1UFNzZIbvcnuiIkVgLKP89Bhuiueqcyxl+TF/BNOVh0VqpzUndQ0 jG4/kUSY6guaQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C6B18684FB for ; Wed, 12 Nov 2025 05:43:23 -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 2coAN-eUsZXg for ; Wed, 12 Nov 2025 05:43:23 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951403; bh=Jd38FUsJzdJrKAcO4IA07t37KMFpp1YSxYilE+UykJY=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=poG42Hc1KFcgEyE+vqeIuHo2NxCEVPEtOMhxt6sGcn1y140nj6nKhXZpFKSkV8hD8 cWOB1pCq4GCU6jzGn3T2hbO4Ag6KJ65ldb/ykYOmld+8ksm3oRMK4dFm0u9I/u85pz 18qp2xlKlqeVsipaZSo6uiGmQ0FGie/uxyfaRKEPF4+Qj/yLeyJ+SXpxwIad3bW8wE jI0x0RPiY8zeYQ1vwgZeUQIyMUnzAmM1hQoFAz3lNJeiddFNhz7exCZ0jF9+LPF5pE uZxX27oUBafMfN1UFNzZIbvcnuiIkVgLKP89Bhuiueqcyxl+TF/BNOVh0VqpzUndQ0 jG4/kUSY6guaQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id B69F8684F1 for ; Wed, 12 Nov 2025 05:43:23 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951401; bh=c0m2ZP8iXVRIvUCaNy4KmQNMMEBDDS+FhxEeFu010yM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=od34LLQUeO9GEEEdDumEFv5QX2aOLBVVxQtcxMPJ+XryVvtHyEQFJFnCwYM3PohP0 JW541YOoGT3CRHkJ4Gsg4KSMzzajA/CESOZdiEpzhY8O1N6jJmjU2I/jWl8I/n4+iM clL4H5wE3Gt3O7WPEOkbB2RmZfuQNNynLxTaqLa1idRF2Xdhyo++HcAaUW94aAIi85 NayTd9Ix3DBZTzljzOARJYSfJOHxOJFjSh2bfh8d/+QNObA/AYNzTk6S8BkMXlTeW2 UrqHjVKxsivvBUlPQZPmqMmaLAewUictkMTaXEzuHq7KxiME8pgV2i/fGWRTtv1qWe TGWMEL/njFHLg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id B0BB6684F6; Wed, 12 Nov 2025 05:43:21 -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 10026) with ESMTP id Su82sidavtil; Wed, 12 Nov 2025 05:43:21 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951396; bh=sC1cwxi0zTXWbH6pun9ySXzgIiGucihl/DyWTwm3IlI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bifpwfhAZmpTeRAzvR6XkM8RO5gY5/0gtQa7jt3HuW2k9kq/wmeU3RyoyZ3ijrffv VT3/agAXhp5TjsqqYUhAb+uGD7AfwRkBcTD5vPSlP3q0LeJETxyVpxhZqDDVDPMOAl bijebFTLaXmbJbTaD7Bekx3aSRck3T8g0HzSICAv6OeTE6QXCg69iP8xn9Okxg1+kf Ym08FWYzOE4ktfPPNjm5+OqZrUNN0FcC50n8aof6Bw900RrcllW+XCFzTOvBtWnf5B Dp3shkB+mDmKqnhVH+MMDN/3PwEDEiRh5Cd5b4a/MQ3a5H3qJbEmEskMr3lEEKJvtn AzxNFWatRWN/w== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 7996D682E4; Wed, 12 Nov 2025 05:43:16 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Wed, 12 Nov 2025 05:42:45 -0700 Message-ID: <20251112124252.1081477-5-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251112124252.1081477-1-sjg@u-boot.org> References: <20251112124252.1081477-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: QMGWKCOPBLNORWWHTUIDCDBACVZA6U3H X-Message-ID-Hash: QMGWKCOPBLNORWWHTUIDCDBACVZA6U3H X-MailFrom: sjg@u-boot.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 4/5] luks: Split out crypt reading into its own function List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass In preparation for adding support for a new algorithm, move the decryption part of blkmap_crypt_read() into its own function. Co-developed-by: Claude Signed-off-by: Simon Glass --- drivers/block/blkmap_crypt.c | 67 ++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/drivers/block/blkmap_crypt.c b/drivers/block/blkmap_crypt.c index bc77ddc2751..2de6be23662 100644 --- a/drivers/block/blkmap_crypt.c +++ b/drivers/block/blkmap_crypt.c @@ -45,37 +45,17 @@ struct blkmap_crypt { u8 essiv_key[32]; }; -static ulong blkmap_crypt_read(struct blkmap *bm, struct blkmap_slice *bms, - lbaint_t blknr, lbaint_t blkcnt, void *buffer) +static ulong crypt_read_cbc(struct blkmap *bm, struct blkmap_crypt *bmc, + lbaint_t blknr, lbaint_t blkcnt, + u8 *encrypted_buf, void *buffer) { - struct blkmap_crypt *bmc = container_of(bms, struct blkmap_crypt, slice); struct blk_desc *bd = dev_get_uclass_plat(bm->blk); - struct blk_desc *src_bd = dev_get_uclass_plat(bmc->blk); - lbaint_t src_blknr, blocks_read; - u8 *encrypted_buf, *dest = buffer; u8 expkey[AES256_EXPAND_KEY_LENGTH]; u8 iv[AES_BLOCK_LENGTH]; + u8 *dest = buffer; u64 sector; lbaint_t i; - /* Allocate buffer for encrypted data */ - encrypted_buf = malloc_cache_aligned(blkcnt * src_bd->blksz); - if (!encrypted_buf) - return 0; - - /* - * Calculate source block number (LUKS payload offset + requested - * block) - */ - src_blknr = bmc->blknr + bmc->payload_offset + blknr; - - /* Read encrypted data from underlying device */ - blocks_read = blk_read(bmc->blk, src_blknr, blkcnt, encrypted_buf); - if (blocks_read != blkcnt) { - free(encrypted_buf); - return 0; - } - /* Expand AES key */ aes_expand_key(bmc->master_key, bmc->key_size * 8, expkey); @@ -116,11 +96,48 @@ static ulong blkmap_crypt_read(struct blkmap *bm, struct blkmap_slice *bms, dest + i * bd->blksz, bd->blksz / AES_BLOCK_LENGTH); } - free(encrypted_buf); return blkcnt; } +static ulong blkmap_crypt_read(struct blkmap *bm, struct blkmap_slice *bms, + lbaint_t blknr, lbaint_t blkcnt, void *buffer) +{ + struct blkmap_crypt *bmc = container_of(bms, struct blkmap_crypt, slice); + struct blk_desc *src_bd = dev_get_uclass_plat(bmc->blk); + lbaint_t src_blknr, blocks_read; + u8 *encrypted_buf; + ulong result; + + /* Allocate buffer for encrypted data */ + encrypted_buf = malloc_cache_aligned(blkcnt * src_bd->blksz); + if (!encrypted_buf) + return 0; + + /* + * Calculate source block number (LUKS payload offset + requested + * block) + */ + src_blknr = bmc->blknr + bmc->payload_offset + blknr; + + /* Read encrypted data from underlying device */ + blocks_read = blk_read(bmc->blk, src_blknr, blkcnt, encrypted_buf); + if (blocks_read != blkcnt) { + free(encrypted_buf); + return 0; + } + + if (blknr == 0 && blkcnt >= 1) { + log_debug("First 32 bytes of ENCRYPTED data:\n"); + log_debug_hex("", encrypted_buf, 32); + } + + result = crypt_read_cbc(bm, bmc, blknr, blkcnt, encrypted_buf, buffer); + free(encrypted_buf); + + return result; +} + static void blkmap_crypt_destroy(struct blkmap *bm, struct blkmap_slice *bms) { struct blkmap_crypt *bmc = container_of(bms, struct blkmap_crypt, slice); From patchwork Wed Nov 12 12:42:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 691 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951407; bh=8DHiwfCsQCoa+JIGj14lxYO7gg6RoDMDz/V0qpcQ0J8=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=DFx7HMlYMxQthO1cQ0JolXcJTSoc4cA9PbTQR3HAuDUR48wc5QGao1gV37zQrkLGZ G+ji5K1RMktawl75NoijFw1owFM9AlWB+3q82j+nqXDWnpJs++guDPSVI4ng2ArVYC 7hNpO2FqYXngVTrj1LLUhh9pxvo5YZdtqgYmu9qGo5ibX1ASmqwe3InKUr2yN4xB9o sXlL8a8P5xbjL4R4c6tsuBAeEeRTgiEaukm4I5CK7l3qOqrhhriRgnQ7VhL+bx1vR+ jwCvYK1wpQwRFxOslnDqre5DlzvDbaucp8H2KKhVAFCCEVpM4ufPAAVkbBlIdjUUaX uu4oHAORM3JXQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 3D6C3682E4 for ; Wed, 12 Nov 2025 05:43:27 -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 QN9zGVfcYHt2 for ; Wed, 12 Nov 2025 05:43:27 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951407; bh=8DHiwfCsQCoa+JIGj14lxYO7gg6RoDMDz/V0qpcQ0J8=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=DFx7HMlYMxQthO1cQ0JolXcJTSoc4cA9PbTQR3HAuDUR48wc5QGao1gV37zQrkLGZ G+ji5K1RMktawl75NoijFw1owFM9AlWB+3q82j+nqXDWnpJs++guDPSVI4ng2ArVYC 7hNpO2FqYXngVTrj1LLUhh9pxvo5YZdtqgYmu9qGo5ibX1ASmqwe3InKUr2yN4xB9o sXlL8a8P5xbjL4R4c6tsuBAeEeRTgiEaukm4I5CK7l3qOqrhhriRgnQ7VhL+bx1vR+ jwCvYK1wpQwRFxOslnDqre5DlzvDbaucp8H2KKhVAFCCEVpM4ufPAAVkbBlIdjUUaX uu4oHAORM3JXQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 2B6E9684CC for ; Wed, 12 Nov 2025 05:43:27 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951406; bh=u3acv16ummVS5yn8b684J36AccjRmkCjJzQOE2gA+To=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tou2wL6RVK2/G69Lg+qRphvbWSafk9//7eD7b4GXG0hRpRxiB8Gys+Z2kyS/Rq1x3 WpAr/WuNTwuWcISIEA9PyYibtSVphQxrFnRtwX0y0if2XJjfRbS7nYA3uNcQn+LJtx GpKXW+IaBXXyqcIOfy6q4EscWo7mYKhmcMHLBLaIP3G/ga8iHM6JomNQMOG67c4Mj2 aLD6+clVMe1CiapuXInLSnmIVJC9x7Hq9uij0vEfgbdn6u7aoIAA4GcpqC5tfDKSWU YqP9AOvJFs1jGKEN6jzcpAjZQrkoejQtjz6VC8DhliAnhHnWX2VZbVRd6qq5oQ6Lc8 N1wxmq7rzMO7A== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 307BB684C6; Wed, 12 Nov 2025 05:43: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 10026) with ESMTP id cjTRVgZXf7BD; Wed, 12 Nov 2025 05:43:26 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1762951401; bh=Hnz8uuVOfSfrp6HQM4b8oCHs45iXPjACGMvZWRIlM3Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Z723gEl9RvQGqPlGeqnWfxJGdfaNd9ACZKXalw5EufZPht522u3ZxmBxiSr1QpQqL pni8BD1APjaHlpX7h92C6v0ozsXr4CXfMdGae5c98dobOommKIWVJblQRNUpojupcn Ih6pcTYz/j9uYUIuITBb+XrBLXlkyO3x9HvKwMBFKVlu5wRlvonRF+fZR8tV1DgN54 tia7BQg4oRV+vPPE5NdCfq0pDK86UXk++DEUUDzhnXiWeWR1w/oOLYfBqybh3T6Lob 417TUxZo43BbPv1vRK1+SodQyUz1BxLqdrWa2B7ieNjWWMlGDUv2Bwv/ze8aIEPKcm KSrVClQVVrBoQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 14B7D684CC; Wed, 12 Nov 2025 05:43:21 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Wed, 12 Nov 2025 05:42:46 -0700 Message-ID: <20251112124252.1081477-6-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251112124252.1081477-1-sjg@u-boot.org> References: <20251112124252.1081477-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: GXXPTC6VND2TP5MZDPD3EJM4DQ3YQ3HK X-Message-ID-Hash: GXXPTC6VND2TP5MZDPD3EJM4DQ3YQ3HK X-MailFrom: sjg@u-boot.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 5/5] luks: Add XTS cipher mode support for LUKS2 List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Add support for AES-XTS cipher mode in addition to the existing AES-CBC-ESSIV support. This is the default cipher for LUKS2 volumes. The cipher mode (CBC/XTS) is obtained from the LUKS1 cipher_mode or LUKS2 encryption metadata. XTS mode uses 512-byte block numbers for IV generation (plain64), matching dm-crypt behavior. LUKS2 typically uses 4096-byte sectors for XTS encryption but the IV is based on 512-byte block numbers. Fix the blkmap-size calculation to exclude the LUKS header/payload offset. Update the LUKSv2 test to check reading a file. Co-developed-by: Claude Signed-off-by: Simon Glass --- drivers/block/blkmap_crypt.c | 205 +++++++++++++++++++++++++++++++++++ drivers/block/luks.c | 36 +++++- include/blkmap.h | 13 ++- include/luks.h | 2 +- test/boot/luks.c | 9 +- 5 files changed, 252 insertions(+), 13 deletions(-) diff --git a/drivers/block/blkmap_crypt.c b/drivers/block/blkmap_crypt.c index 2de6be23662..ff01768e05a 100644 --- a/drivers/block/blkmap_crypt.c +++ b/drivers/block/blkmap_crypt.c @@ -29,6 +29,7 @@ * @master_key: Decrypted master key for decryption * @key_size: Size of the master key in bytes (must be <= 128) * @payload_offset: Offset in sectors from lblknr to actual encrypted payload + * @cipher_mode: Cipher mode (CBC or XTS) * @sector_size: Sector size for IV calculation (typically 512 or 4096) * @use_essiv: True if ESSIV mode is used for IV generation (CBC only) * @essiv_key: ESSIV key (SHA256 hash of master key) @@ -40,11 +41,202 @@ struct blkmap_crypt { u8 master_key[128]; u32 key_size; u32 payload_offset; + enum blkmap_crypt_mode cipher_mode; u32 sector_size; bool use_essiv; u8 essiv_key[32]; }; +/** + * process_xts_sector() - Read, decrypt and copy one XTS sector + * + * This reads an encrypted sector from disk, decrypts it using AES-XTS with + * the plain64 IV mode, and copies the requested portion to the output buffer. + * Handles partial sector reads at the start and end of the requested range. + * + * @bmc: Blkmap crypt context with key and device info + * @ctx: Initialized AES-XTS context + * @cur_sector: Current XTS sector number being processed + * @start_sector: First XTS sector in the requested range + * @end_sector: Last XTS sector in the requested range + * @blks_per_sect: Number of 512-byte blocks per XTS sector + * @offset_in_first_sector: Byte offset within first sector to start copying + * @blkcnt: Total number of blocks requested + * @buf: Buffer for reading/decrypting one full sector + * @dest: Output buffer for decrypted data + * @blksz: Block-device block size (typically 512 bytes) + * @blocks_donep: Count of blocks copied so far (updated) + * Return: 0 on success, -EIO on read failure, other negative on decrypt failure + */ +static int process_xts_sector(struct blkmap_crypt *bmc, + mbedtls_aes_xts_context *ctx, lbaint_t cur_sector, + lbaint_t start_sector, lbaint_t end_sector, + uint blks_per_sect, uint offset_in_first_sector, + lbaint_t blkcnt, u8 *buf, u8 *dest, uint blksz, + lbaint_t *blocks_donep) +{ + lbaint_t start_blk = cur_sector * blks_per_sect; + lbaint_t src_blk = bmc->blknr + bmc->payload_offset + start_blk; + uint copy_offset = 0; + lbaint_t iv_sector; + u8 data_unit[16]; + uint copy_len; + lbaint_t j; + int ret; + + log_debug("XTS: cur_sector=%lu bmc->blknr=%lu bmc->payload_offset=%u src_blk=%lu\n", + cur_sector, bmc->blknr, bmc->payload_offset, src_blk); + + /* Read entire sector from disk */ + if (blk_read(bmc->blk, src_blk, blks_per_sect, buf) != + blks_per_sect) { + log_err("Failed to read sector %lu\n", cur_sector); + return -EIO; + } + + /* + * Prepare data_unit (IV) for XTS decryption. + * For plain64 IV mode, the IV is the 512-byte sector number, + * not the larger XTS sector number. This matches dm-crypt behavior. + */ + iv_sector = start_blk; + memset(data_unit, '\0', sizeof(data_unit)); + for (j = 0; j < 8; j++) + data_unit[j] = (iv_sector >> (j * 8)) & 0xff; + + /* Decrypt entire sector */ + ret = mbedtls_aes_crypt_xts(ctx, MBEDTLS_AES_DECRYPT, bmc->sector_size, + data_unit, buf, buf); + if (ret) { + log_err("XTS decrypt sector %lu failed: %d\n", cur_sector, ret); + return ret; + } + + /* Calculate which portion of this sector to copy */ + if (cur_sector == start_sector) + copy_offset = offset_in_first_sector; + + if (cur_sector == end_sector) { + /* Last sector: copy only up to the end of requested data */ + uint remaining = (blkcnt - *blocks_donep) * blksz; + + copy_len = remaining; + } else { + /* Not the last sector: copy from offset to end of sector */ + copy_len = bmc->sector_size - copy_offset; + } + + /* Copy decrypted data to output buffer */ + memcpy(dest + *blocks_donep * blksz, buf + copy_offset, copy_len); + *blocks_donep += copy_len / blksz; + + return 0; +} + +/** + * crypt_read_xts() - Decrypt data using AES-XTS cipher mode + * + * Decrypts blocks from an encrypted device using AES-XTS with plain64 IV mode. + * Handles requests that span multiple XTS sectors and partial sector reads. + * The IV for each XTS sector is the 512-byte block number (not the larger + * XTS sector number), matching dm-crypt's plain64 IV generation. + * + * @bm: Blkmap device context + * @bmc: Blkmap crypt context with encryption parameters + * @blknr: Starting block number (relative to decrypted device) + * @blkcnt: Number of blocks to read + * @buffer: Output buffer for decrypted data + * Return: number of blocks successfully decrypted, or negative error code + * (-ENOMEM if buffer allocation failed, -EINVAL if key setup failed, + * -EIO or other negative on sector read/decrypt failure) + */ +static ulong crypt_read_xts(struct blkmap *bm, struct blkmap_crypt *bmc, + lbaint_t blknr, lbaint_t blkcnt, void *out_buf) +{ + struct blk_desc *bd = dev_get_uclass_plat(bm->blk); + lbaint_t start_sector, end_sector, cur_sect; + uint offset_in_first_sector; + mbedtls_aes_xts_context ctx; + lbaint_t blocks_done; + uint blks_per_sect; + u8 *buf; + int ret; + + blks_per_sect = bmc->sector_size / bd->blksz; + + log_debug("key_size=%u blkcnt=%lu\n", bmc->key_size, blkcnt); + log_debug("XTS: sector_size=%u blocks_per_sector=%u\n", + bmc->sector_size, blks_per_sect); + log_debug("Master key (all %u bytes):\n", bmc->key_size); + log_debug_hex("", bmc->master_key, bmc->key_size); + + /* Calculate which encryption sectors we need */ + start_sector = blknr / blks_per_sect; + end_sector = (blknr + blkcnt - 1) / blks_per_sect; + offset_in_first_sector = (blknr % blks_per_sect) * bd->blksz; + + log_debug("XTS: blknr=%lu blkcnt=%lu start_sector=%lu end_sector=%lu offset=%u\n", + blknr, blkcnt, start_sector, end_sector, + offset_in_first_sector); + + /* Allocate buffer for one full sector */ + buf = malloc_cache_aligned(bmc->sector_size); + if (!buf) { + log_err("Failed to allocate sector buffer\n"); + return -ENOMEM; + } + + mbedtls_aes_xts_init(&ctx); + ret = mbedtls_aes_xts_setkey_dec(&ctx, bmc->master_key, + bmc->key_size * 8); + if (ret) { + log_err("XTS setkey_dec failed: %d\n", ret); + mbedtls_aes_xts_free(&ctx); + free(buf); + return -EINVAL; + } + + /* Process each sector */ + blocks_done = 0; + for (cur_sect = start_sector; cur_sect <= end_sector; cur_sect++) { + ret = process_xts_sector(bmc, &ctx, cur_sect, start_sector, + end_sector, blks_per_sect, + offset_in_first_sector, blkcnt, + buf, out_buf, bd->blksz, &blocks_done); + if (ret) { + mbedtls_aes_xts_free(&ctx); + free(buf); + return ret; + } + } + + free(buf); + mbedtls_aes_xts_free(&ctx); + + log_debug("XTS decryption completed successfully for %lu blocks\n", blkcnt); + if (blknr == 0 && blkcnt >= 1) { + log_debug("First 32 bytes of decrypted data:\n"); + log_debug_hex("", out_buf, 32); + } + + return blkcnt; +} + +/** + * crypt_read_cbc() - Decrypt data using AES-CBC cipher mode + * + * Decrypts blocks from an encrypted device using AES-CBC. Supports both + * plain64 mode (IV = sector number) and ESSIV mode (IV = AES_encrypt(sector + * number, SHA256(master_key))). Used for LUKS1 volumes. + * + * @bm: Blkmap device context + * @bmc: Blkmap crypt context with encryption parameters and ESSIV key + * @blknr: Starting block number (relative to decrypted device) + * @blkcnt: Number of blocks to decrypt + * @encrypted_buf: Buffer containing encrypted data (already read from disk) + * @buffer: Output buffer for decrypted data + * Return: number of blocks successfully decrypted + */ static ulong crypt_read_cbc(struct blkmap *bm, struct blkmap_crypt *bmc, lbaint_t blknr, lbaint_t blkcnt, u8 *encrypted_buf, void *buffer) @@ -132,6 +324,16 @@ static ulong blkmap_crypt_read(struct blkmap *bm, struct blkmap_slice *bms, log_debug_hex("", encrypted_buf, 32); } + if (bmc->cipher_mode == BLKMAP_CRYPT_MODE_XTS) { + result = crypt_read_xts(bm, bmc, blknr, blkcnt, buffer); + /* XTS reads its own data, so free encrypted_buf early */ + free(encrypted_buf); + /* Check for error - result will be negative on failure */ + if ((long)result < 0) + return 0; + return result; + } + result = crypt_read_cbc(bm, bmc, blknr, blkcnt, encrypted_buf, buffer); free(encrypted_buf); @@ -150,6 +352,7 @@ static void blkmap_crypt_destroy(struct blkmap *bm, struct blkmap_slice *bms) int blkmap_map_crypt(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, struct udevice *lblk, lbaint_t lblknr, const u8 *master_key, u32 key_size, u32 payload_offset, + enum blkmap_crypt_mode cipher_mode, u32 sector_size, bool use_essiv, const u8 *essiv_key) { struct blkmap *bm = dev_get_plat(dev); @@ -167,6 +370,8 @@ int blkmap_map_crypt(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, bmc->blknr = lblknr; bmc->key_size = key_size; bmc->payload_offset = payload_offset; + bmc->cipher_mode = cipher_mode; + bmc->sector_size = sector_size; bmc->use_essiv = use_essiv; memcpy(bmc->master_key, master_key, key_size); diff --git a/drivers/block/luks.c b/drivers/block/luks.c index c7e5a3da154..923932c0dad 100644 --- a/drivers/block/luks.c +++ b/drivers/block/luks.c @@ -596,6 +596,7 @@ int luks_create_blkmap(struct udevice *blk, struct disk_partition *pinfo, struct udevice **blkmapp) { u8 essiv_key[SHA256_SUM_LEN]; /* SHA-256 output */ + enum blkmap_crypt_mode cipher_mode; lbaint_t decrypted_size; struct luks1_phdr *hdr; struct luks2_hdr *hdr2; @@ -603,6 +604,7 @@ int luks_create_blkmap(struct udevice *blk, struct disk_partition *pinfo, struct udevice *dev; uint payload_offset; int ret, version; + u32 sector_size; bool use_essiv; if (!blk || !pinfo || !master_key || !label || !blkmapp) @@ -698,12 +700,26 @@ int luks_create_blkmap(struct udevice *blk, struct disk_partition *pinfo, /* Convert byte offset to sectors */ payload_offset = segment_offset / desc->blksz; - /* Check if ESSIV mode is used */ + /* Parse cipher mode from encryption string */ encryption = ofnode_read_string(segment0_node, "encryption"); - if (encryption) + if (encryption) { use_essiv = strstr(encryption, "essiv"); - else + /* Check if XTS mode is used */ + if (strstr(encryption, "xts")) + cipher_mode = BLKMAP_CRYPT_MODE_XTS; + else + cipher_mode = BLKMAP_CRYPT_MODE_CBC; + } else { use_essiv = false; + cipher_mode = BLKMAP_CRYPT_MODE_CBC; + } + + /* Read sector_size if present */ + if (ofnode_read_u32(segment0_node, "sector_size", §or_size)) { + /* If not found, default to 512 */ + sector_size = 512; + } + log_debug("LUKS2: sector_size=%u\n", sector_size); abuf_uninit(&fdt_buf); free(json_data); @@ -711,11 +727,20 @@ int luks_create_blkmap(struct udevice *blk, struct disk_partition *pinfo, /* LUKS1 */ hdr = (struct luks1_phdr *)buf; - /* Check if ESSIV mode is used */ + /* Parse cipher mode from cipher_mode string */ use_essiv = strstr(hdr->cipher_mode, "essiv"); + /* Check if XTS mode is used */ + if (strstr(hdr->cipher_mode, "xts")) + cipher_mode = BLKMAP_CRYPT_MODE_XTS; + else + cipher_mode = BLKMAP_CRYPT_MODE_CBC; /* Get payload offset */ payload_offset = be32_to_cpu(hdr->payload_offset); + + /* LUKS1 always uses 512-byte sectors */ + sector_size = 512; + log_debug("LUKS1: sector_size=%u\n", sector_size); } /* Create blkmap device */ @@ -747,7 +772,8 @@ int luks_create_blkmap(struct udevice *blk, struct disk_partition *pinfo, use_essiv); ret = blkmap_map_crypt(dev, 0, decrypted_size, blk, pinfo->start, master_key, key_size, payload_offset, - use_essiv, use_essiv ? essiv_key : NULL); + cipher_mode, sector_size, use_essiv, + use_essiv ? essiv_key : NULL); if (ret) { log_debug("failed to map encrypted partition\n"); blkmap_destroy(dev); diff --git a/include/blkmap.h b/include/blkmap.h index a0f46748b92..8a664edc33f 100644 --- a/include/blkmap.h +++ b/include/blkmap.h @@ -9,6 +9,14 @@ #include +/** + * enum blkmap_crypt_mode - Cipher mode for encrypted block devices + */ +enum blkmap_crypt_mode { + BLKMAP_CRYPT_MODE_CBC = 0, /* AES-CBC */ + BLKMAP_CRYPT_MODE_XTS = 1, /* AES-XTS */ +}; + /** * struct blkmap - Block map * @@ -80,13 +88,16 @@ int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, * @master_key: Decrypted master key for decryption * @key_size: Size of the master key in bytes (must be <= 128) * @payload_offset: Offset in sectors from lblknr to actual encrypted payload - * @use_essiv: True to use ESSIV mode, false for plain64 mode + * @cipher_mode: Cipher mode (CBC or XTS) + * @sector_size: Sector size for IV calculation (typically 512 or 4096) + * @use_essiv: True to use ESSIV mode, false for plain64 mode (CBC only) * @essiv_key: ESSIV key (SHA256 of master key), or NULL if use_essiv is false * Returns: 0 on success, negative error code on failure */ int blkmap_map_crypt(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, struct udevice *lblk, lbaint_t lblknr, const u8 *master_key, u32 key_size, u32 payload_offset, + enum blkmap_crypt_mode cipher_mode, u32 sector_size, bool use_essiv, const u8 *essiv_key); /** diff --git a/include/luks.h b/include/luks.h index 4f65f3029f8..6c39db7a2d2 100644 --- a/include/luks.h +++ b/include/luks.h @@ -141,7 +141,7 @@ int luks_show_info(struct udevice *blk, struct disk_partition *pinfo); * luks_unlock() - Unlock a LUKS partition with a passphrase * * This attempts to decrypt the master key using the provided passphrase. - * Currently only supports LUKS1 with PBKDF2 and AES-CBC. + * Supports LUKS1 (PBKDF2, AES-CBC/XTS) and LUKS2 (PBKDF2/Argon2, AES-XTS). * * @blk: Block device * @pinfo: Partition information diff --git a/test/boot/luks.c b/test/boot/luks.c index ec95b241d8a..6bf613f3b08 100644 --- a/test/boot/luks.c +++ b/test/boot/luks.c @@ -287,12 +287,9 @@ static int bootstd_test_luks2_unlock(struct unit_test_state *uts) desc = blk_get_devnum_by_uclass_idname("blkmap", 0); ut_assertnonnull(desc); - /* at present this fails due to incorrect decryption */ - if (0) { - ut_assertok(fs_set_blk_dev_with_part(desc, 0)); - ut_assertok(fs_size("/bin/bash", &file_size)); - ut_asserteq(5, file_size); - } + ut_assertok(fs_set_blk_dev_with_part(desc, 0)); + ut_assertok(fs_size("/bin/bash", &file_size)); + ut_asserteq(5, file_size); /* Test unlocking with wrong passphrase */ ut_asserteq(1, run_command("luks unlock mmc c:2 wrongpass", 0));