From: Pranav Rajendran <pranavkasthuri@gmail.com>
To: u-boot@lists.u-boot-project.org
Cc: trini@konsulko.com, sjg@chromium.org,
philippe.reynes@softathome.com,
Pranav Rajendran <pranavkasthuri@gmail.com>
Subject: [PATCH v2 5/5] test: boot: add regression tests for the FIT cipher bounds checks
Date: Tue, 25 Aug 2026 15:19:53 +0100 [thread overview]
Message-ID: <20260825141953.9534-6-pranavkasthuri@gmail.com> (raw)
In-Reply-To: <20260825141953.9534-1-pranavkasthuri@gmail.com>
Add a fit_cipher unit test suite, gated on CONFIG_FIT_CIPHER like the
code it exercises, covering the three defects fixed in this series:
- image_aes_decrypt() rejects a cipher_len that is not a whole number
of AES blocks
- image_aes_decrypt() rejects an unciphered size larger than the
ciphertext, and accepts the boundary case where they are equal
- fit_image_get_data_size_unciphered() rejects a 'data-size-unciphered'
property that is not exactly one fdt32_t long, built via a minimal
FIT constructed with libfdt, and accepts a correctly sized one
Signed-off-by: Pranav Rajendran <pranavkasthuri@gmail.com>
---
v2:
- New in v2, per Simon's request for regression tests on this series.
test/boot/Makefile | 1 +
test/boot/fit_cipher.c | 113 +++++++++++++++++++++++++++++++++++++++++
test/cmd_ut.c | 2 +
3 files changed, 116 insertions(+)
create mode 100644 test/boot/fit_cipher.c
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 59a87028704..cef2a236d9b 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -18,6 +18,7 @@ ifdef CONFIG_UT_DM
obj-$(CONFIG_$(PHASE_)OF_LIBFDT) += image_fdt.o
endif
endif
+obj-$(CONFIG_$(PHASE_)FIT_CIPHER) += fit_cipher.o
obj-$(CONFIG_$(PHASE_)FIT_VERITY) += fit_verity.o
obj-$(CONFIG_MEASURED_BOOT) += measurement.o
diff --git a/test/boot/fit_cipher.c b/test/boot/fit_cipher.c
new file mode 100644
index 00000000000..b98c69fcb0b
--- /dev/null
+++ b/test/boot/fit_cipher.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Regression tests for the FIT cipher bounds checks in
+ * image_aes_decrypt() and fit_image_get_data_size_unciphered().
+ *
+ * Copyright 2026 Pranav Rajendran <pranavkasthuri@gmail.com>
+ */
+
+#include <errno.h>
+#include <image.h>
+#include <uboot_aes.h>
+#include <u-boot/aes.h>
+#include <linux/libfdt.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define FIT_CIPHER_TEST(_name, _flags) UNIT_TEST(_name, _flags, fit_cipher)
+
+/* A cipher_len that is not a whole number of AES blocks must be rejected */
+static int fit_cipher_test_unaligned_len(struct unit_test_state *uts)
+{
+ struct image_cipher_info info;
+ unsigned char key[AES128_KEY_LENGTH] = { 0 };
+ unsigned char iv[AES_BLOCK_LENGTH] = { 0 };
+ unsigned char cipher[AES_BLOCK_LENGTH + 1] = { 0 };
+ void *data = NULL;
+ size_t size = 0;
+ int ret;
+
+ memset(&info, 0, sizeof(info));
+ info.cipher = image_get_cipher_algo("aes128");
+ ut_assertnonnull(info.cipher);
+ info.key = key;
+ info.iv = iv;
+
+ ret = image_aes_decrypt(&info, cipher, sizeof(cipher), &data, &size);
+ ut_asserteq(-EINVAL, ret);
+ ut_assertnull(data);
+
+ return 0;
+}
+FIT_CIPHER_TEST(fit_cipher_test_unaligned_len, 0);
+
+/*
+ * An unciphered size larger than the ciphertext must be rejected; a size
+ * exactly equal to the ciphertext length is the valid boundary case.
+ */
+static int fit_cipher_test_oversized_unciphered_size(struct unit_test_state *uts)
+{
+ struct image_cipher_info info;
+ unsigned char key[AES128_KEY_LENGTH] = { 0 };
+ unsigned char iv[AES_BLOCK_LENGTH] = { 0 };
+ unsigned char cipher[AES_BLOCK_LENGTH * 2] = { 0 };
+ void *data = NULL;
+ size_t size = 0;
+ int ret;
+
+ memset(&info, 0, sizeof(info));
+ info.cipher = image_get_cipher_algo("aes128");
+ ut_assertnonnull(info.cipher);
+ info.key = key;
+ info.iv = iv;
+
+ info.size_unciphered = sizeof(cipher) + 1;
+ ret = image_aes_decrypt(&info, cipher, sizeof(cipher), &data, &size);
+ ut_asserteq(-EINVAL, ret);
+ ut_assertnull(data);
+
+ /* the boundary itself, size_unciphered == cipher_len, is valid */
+ info.size_unciphered = sizeof(cipher);
+ ut_assertok(image_aes_decrypt(&info, cipher, sizeof(cipher), &data,
+ &size));
+ ut_assertnonnull(data);
+ ut_asserteq(sizeof(cipher), size);
+ free(data);
+
+ return 0;
+}
+FIT_CIPHER_TEST(fit_cipher_test_oversized_unciphered_size, 0);
+
+/*
+ * A 'data-size-unciphered' property that is not exactly one fdt32_t long
+ * must be rejected rather than read out of bounds.
+ */
+static int fit_cipher_test_data_size_unciphered_len(struct unit_test_state *uts)
+{
+ char fit[512];
+ int images, img, ret;
+ u16 truncated = 0x1234;
+ fdt32_t valid = cpu_to_fdt32(0x100);
+ size_t data_size = 0;
+
+ ut_assertok(fdt_create_empty_tree(fit, sizeof(fit)));
+ images = fdt_add_subnode(fit, 0, "images");
+ ut_assert(images >= 0);
+
+ img = fdt_add_subnode(fit, images, "kernel");
+ ut_assert(img >= 0);
+ ut_assertok(fdt_setprop(fit, img, "data-size-unciphered",
+ &truncated, sizeof(truncated)));
+
+ ret = fit_image_get_data_size_unciphered(fit, img, &data_size);
+ ut_asserteq(-EINVAL, ret);
+
+ /* a correctly sized property still works */
+ ut_assertok(fdt_setprop(fit, img, "data-size-unciphered",
+ &valid, sizeof(valid)));
+ ut_assertok(fit_image_get_data_size_unciphered(fit, img, &data_size));
+ ut_asserteq(0x100, data_size);
+
+ return 0;
+}
+FIT_CIPHER_TEST(fit_cipher_test_data_size_unciphered_len, 0);
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 4328670d0d6..95e86f7dcf6 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -59,6 +59,7 @@ SUITE_DECL(env);
SUITE_DECL(exit);
SUITE_DECL(fdt);
SUITE_DECL(fdt_overlay);
+SUITE_DECL(fit_cipher);
SUITE_DECL(fit_verity);
SUITE_DECL(font);
SUITE_DECL(hush);
@@ -88,6 +89,7 @@ static struct suite suites[] = {
SUITE(exit, "shell exit and variables"),
SUITE(fdt, "fdt command"),
SUITE(fdt_overlay, "device tree overlays"),
+ SUITE(fit_cipher, "FIT cipher bounds checks"),
SUITE(fit_verity, "FIT dm-verity cmdline generation"),
SUITE(font, "font command"),
SUITE(hush, "hush behaviour"),
--
2.50.1 (Apple Git-155)
prev parent reply other threads:[~2026-08-25 16:03 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-15 22:07 [PATCH v1 0/3] fit: cipher: bounds checks on the ciphered image path Pranav Rajendran
2026-08-15 22:07 ` [PATCH v1 1/3] lib: aes: reject a ciphertext length that is not a whole number of blocks Pranav Rajendran
2026-08-25 12:52 ` Simon Glass
2026-08-15 22:07 ` [PATCH v1 2/3] image-fit: check the length of the data-size-unciphered property Pranav Rajendran
2026-08-25 12:52 ` Simon Glass
2026-08-15 22:07 ` [PATCH v1 3/3] lib: aes: reject an unciphered size larger than the ciphertext Pranav Rajendran
2026-08-25 12:52 ` Simon Glass
2026-08-25 12:53 ` [v1,0/3] fit: cipher: bounds checks on the ciphered image path Simon Glass
2026-08-25 14:19 ` [PATCH v2 0/5] " Pranav Rajendran
2026-08-25 14:19 ` [PATCH v2 1/5] lib: aes: reject a ciphertext length that is not a whole number of blocks Pranav Rajendran
2026-08-25 14:19 ` [PATCH v2 2/5] image-fit: check the length of the data-size-unciphered property Pranav Rajendran
2026-08-25 14:19 ` [PATCH v2 3/5] lib: aes: reject an unciphered size larger than the ciphertext Pranav Rajendran
2026-08-25 14:19 ` [PATCH v2 4/5] include: u-boot: aes: make disabled cipher stubs static inline Pranav Rajendran
2026-08-25 14:19 ` Pranav Rajendran [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260825141953.9534-6-pranavkasthuri@gmail.com \
--to=pranavkasthuri@gmail.com \
--cc=philippe.reynes@softathome.com \
--cc=sjg@chromium.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.u-boot-project.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox