* [PATCH v3] tests: add functional tests for ecb/cbc helpers
@ 2026-01-02 6:44 Srish Srinivasan
0 siblings, 0 replies; only message in thread
From: Srish Srinivasan @ 2026-01-02 6:44 UTC (permalink / raw)
To: grub-devel; +Cc: daniel.kiper, development, sudhakar, sridharm, ssrish
Test the following helper functions using AES with 128, 192, and
256 bit keys:
grub_crypto_ecb_encrypt
grub_crypto_ecb_decrypt
grub_crypto_cbc_encrypt
grub_crypto_cbc_decrypt
Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
Reviewed-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Glenn Washburn <development@efficientek.com>
---
docs/grub.texi | 5 +
grub-core/Makefile.core.def | 5 +
grub-core/tests/crypto_cipher_mode_test.c | 197 +++++++++++++++++++
grub-core/tests/crypto_cipher_mode_vectors.h | 135 +++++++++++++
grub-core/tests/lib/functional_test.c | 1 +
5 files changed, 343 insertions(+)
create mode 100644 grub-core/tests/crypto_cipher_mode_test.c
create mode 100644 grub-core/tests/crypto_cipher_mode_vectors.h
diff --git a/docs/grub.texi b/docs/grub.texi
index 7181009b6..48584068b 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4092,6 +4092,7 @@ Modules can be loaded via the @command{insmod} (@pxref{insmod}) command.
* dm_nv_module::
* drivemap_module::
* dsa_sexp_test_module::
+* crypto_cipher_mode_test_module::
* echo_module::
* efi_gop_module::
* efi_uga_module::
@@ -4677,6 +4678,10 @@ mappings. @xref{drivemap} for more information.
@section dsa_sexp_test
This module provides a test of the libgcrypt DSA functionality in GRUB.
+@node crypto_cipher_mode_test_module
+@section crypto_cipher_mode_test
+This module performs various cipher mode encryption/decryption tests
+
@node echo_module
@section echo
This module provides support for the @command{echo} to display a line of text.
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index fa4bc54aa..0cf155128 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2272,6 +2272,11 @@ module = {
common = tests/argon2_test.c;
};
+module = {
+ name = crypto_cipher_mode_test;
+ common = tests/crypto_cipher_mode_test.c;
+};
+
module = {
name = legacy_password_test;
common = tests/legacy_password_test.c;
diff --git a/grub-core/tests/crypto_cipher_mode_test.c b/grub-core/tests/crypto_cipher_mode_test.c
new file mode 100644
index 000000000..68f316421
--- /dev/null
+++ b/grub-core/tests/crypto_cipher_mode_test.c
@@ -0,0 +1,197 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2025 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/test.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/crypto.h>
+
+#include "crypto_cipher_mode_vectors.h"
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/* Perform cipher lookup, handle init, and key setting. */
+static grub_crypto_cipher_handle_t
+handle_init (struct vector vec, grub_crypto_cipher_handle_t handle)
+{
+ gcry_err_code_t err;
+
+ const gcry_cipher_spec_t *cipher = grub_crypto_lookup_cipher_by_name (vec.cipher);
+ grub_test_assert (cipher != NULL, "\n%s: cipher lookup failed for %s", vec.mode, vec.cipher);
+ if (cipher == NULL)
+ return NULL;
+
+ handle = grub_crypto_cipher_open (cipher);
+ grub_test_assert (handle != NULL, "\n%s: handle init failed for %s", vec.mode, vec.cipher);
+ if (handle == NULL)
+ return NULL;
+
+ err = grub_crypto_cipher_set_key (handle, (grub_uint8_t *) vec.key, vec.keylen);
+ grub_test_assert (err == GPG_ERR_NO_ERROR, "\n%s: key set of size %d failed for %s with err = %d",
+ vec.mode, vec.keylen, vec.cipher, err);
+ if (err != GPG_ERR_NO_ERROR)
+ {
+ grub_crypto_cipher_close (handle);
+ return NULL;
+ }
+
+ return handle;
+}
+
+static void
+ecb_test (struct vector vec)
+{
+ gcry_err_code_t gcry_err;
+ grub_crypto_cipher_handle_t handle = NULL;
+ grub_uint8_t *plaintext = NULL, *ciphertext = NULL;
+ grub_int32_t rc;
+
+ handle = handle_init (vec, handle);
+ if (handle == NULL)
+ return;
+
+ /* Test encryption. */
+ ciphertext = grub_zalloc (vec.plen);
+ grub_test_assert (ciphertext != NULL, "\necb: ciphertext buffer allocation failed");
+ if (ciphertext == NULL)
+ goto out_handle;
+
+ gcry_err = grub_crypto_ecb_encrypt (handle, ciphertext, vec.ptext, vec.plen);
+ grub_test_assert (gcry_err == GPG_ERR_NO_ERROR, "\necb: encryption failed with err = %d",
+ gcry_err);
+ if (gcry_err != GPG_ERR_NO_ERROR)
+ goto out_ct;
+
+ rc = grub_memcmp (ciphertext, vec.ctext, vec.plen);
+ grub_test_assert (rc == 0, "\necb: ciphertext mismatch after encryption");
+ if (rc != 0)
+ goto out_ct;
+
+ /* Test decryption. */
+ plaintext = grub_zalloc (vec.plen);
+ grub_test_assert (plaintext != NULL, "\necb: plaintext buffer allocation failed");
+ if (plaintext == NULL)
+ goto out_ct;
+
+ gcry_err = grub_crypto_ecb_decrypt (handle, plaintext, ciphertext, vec.plen);
+ grub_test_assert (gcry_err == GPG_ERR_NO_ERROR, "\necb: decryption failed failed with err = %d",
+ gcry_err);
+ if (gcry_err != GPG_ERR_NO_ERROR)
+ goto out_pt;
+
+ rc = grub_memcmp (plaintext, vec.ptext, vec.plen);
+ grub_test_assert (rc == 0, "\necb: plaintext mismatch after decryption");
+
+out_pt:
+ grub_free(plaintext);
+out_ct:
+ grub_free(ciphertext);
+out_handle:
+ grub_crypto_cipher_close(handle);
+}
+
+static void
+cbc_test (struct vector vec)
+{
+ gcry_err_code_t gcry_err;
+ grub_crypto_cipher_handle_t handle = NULL;
+ grub_uint8_t *plaintext = NULL, *ciphertext = NULL;
+ grub_uint32_t *iv = NULL;
+ grub_int32_t rc;
+
+ handle = handle_init (vec, handle);
+ if (handle == NULL)
+ return;
+
+ /* Test Encryption */
+ iv = grub_malloc(vec.ivlen);
+ grub_test_assert (iv != NULL, "\ncbc: IV buffer allocation failed");
+ if (iv == NULL)
+ goto out_handle;
+
+ grub_memcpy (iv, vec.iv_in, vec.ivlen);
+
+ ciphertext = grub_zalloc (vec.plen);
+ grub_test_assert (ciphertext != NULL, "\ncbc: ciphertext buffer allocation failed");
+ if (ciphertext == NULL)
+ goto out_iv;
+
+ gcry_err = grub_crypto_cbc_encrypt (handle, ciphertext, vec.ptext, vec.plen, iv);
+ grub_test_assert (gcry_err == GPG_ERR_NO_ERROR, "\ncbc: encryption failed with err = %d",
+ gcry_err);
+ if (gcry_err != GPG_ERR_NO_ERROR)
+ goto out_ct;
+
+ rc = grub_memcmp (ciphertext, vec.ctext, vec.plen);
+ grub_test_assert (rc == 0, "\ncbc: ciphertext mismatch after encryption");
+ if (rc != 0)
+ goto out_ct;
+
+ rc = grub_memcmp (iv, vec.iv_out, vec.ivlen);
+ grub_test_assert (rc == 0, "\ncbc: IV out mismatch after encryption");
+ if (rc != 0)
+ goto out_ct;
+
+ /* Test Decryption */
+ grub_memcpy (iv, vec.iv_in, vec.ivlen);
+
+ plaintext = grub_zalloc (vec.plen);
+ grub_test_assert (plaintext != NULL, "\ncbc: plaintext buffer allocation failed");
+ if (plaintext == NULL)
+ goto out_ct;
+
+ gcry_err = grub_crypto_cbc_decrypt (handle, plaintext, ciphertext, vec.plen, iv);
+ grub_test_assert (gcry_err == GPG_ERR_NO_ERROR, "\ncbc: decryption failed with err = %d",
+ gcry_err);
+ if (gcry_err != GPG_ERR_NO_ERROR)
+ goto out_pt;
+
+ rc = grub_memcmp (plaintext, vec.ptext, vec.plen);
+ grub_test_assert (rc == 0, "\ncbc: plaintext mismatch after decryption");
+
+out_pt:
+ grub_free(plaintext);
+out_ct:
+ grub_free(ciphertext);
+out_iv:
+ grub_free(iv);
+out_handle:
+ grub_crypto_cipher_close(handle);
+}
+
+static void
+crypto_cipher_mode_test (void)
+{
+ grub_size_t i;
+
+ for (i = 0; i < ARRAY_SIZE (vecs); i++)
+ {
+ if (grub_strcmp (vecs[i].mode, "ecb") == 0)
+ ecb_test(vecs[i]);
+ else if (grub_strcmp (vecs[i].mode, "cbc") == 0)
+ cbc_test(vecs[i]);
+ else
+ {
+ grub_test_assert(0, "\n%s mode unsupported for testing", vecs[i].mode);
+ return;
+ }
+ }
+}
+
+/* Register example_test method as a functional test. */
+GRUB_FUNCTIONAL_TEST (crypto_cipher_mode_test, crypto_cipher_mode_test);
diff --git a/grub-core/tests/crypto_cipher_mode_vectors.h b/grub-core/tests/crypto_cipher_mode_vectors.h
new file mode 100644
index 000000000..8ef948b46
--- /dev/null
+++ b/grub-core/tests/crypto_cipher_mode_vectors.h
@@ -0,0 +1,135 @@
+struct vector
+{
+ const char *cipher;
+ const char *mode;
+ const char *key;
+ grub_uint32_t keylen;
+ const char *ptext;
+ grub_uint32_t plen;
+ const char *ctext;
+ const char *iv_in;
+ const char *iv_out;
+ grub_uint32_t ivlen;
+} vecs[] = {
+ {
+ .cipher = "aes",
+ .mode = "ecb",
+ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .keylen = 16,
+ .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77"
+ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .plen = 16,
+ .ctext = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
+ "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
+ },
+ {
+ .cipher = "aes",
+ .mode = "ecb",
+ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17",
+ .keylen = 24,
+ .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77"
+ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .plen = 16,
+ .ctext = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
+ "\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
+ },
+ {
+ .cipher = "aes",
+ .mode = "ecb",
+ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .keylen = 32,
+ .ptext = "\x00\x11\x22\x33\x44\x55\x66\x77"
+ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .plen = 16,
+ .ctext = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
+ "\xea\xfc\x49\x90\x4b\x49\x60\x89",
+ },
+ {
+ .cipher = "aes",
+ .mode = "cbc",
+ .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
+ "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
+ .keylen = 16,
+ .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .plen = 32,
+ .ctext = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a"
+ "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a"
+ "\x75\x86\x60\x2d\x25\x3c\xff\xf9"
+ "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1",
+ .iv_in = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
+ "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
+ .iv_out = "\x75\x86\x60\x2d\x25\x3c\xff\xf9"
+ "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1",
+ .ivlen = 16,
+ },
+ {
+ .cipher = "aes",
+ .mode = "cbc",
+ .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
+ "\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+ "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+ .keylen = 24,
+ .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .plen = 64,
+ .ctext = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d"
+ "\x71\x78\x18\x3a\x9f\xa0\x71\xe8"
+ "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4"
+ "\xe5\xe7\x38\x76\x3f\x69\x14\x5a"
+ "\x57\x1b\x24\x20\x12\xfb\x7a\xe0"
+ "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0"
+ "\x08\xb0\xe2\x79\x88\x59\x88\x81"
+ "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd",
+ .iv_in = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .iv_out = "\x08\xb0\xe2\x79\x88\x59\x88\x81"
+ "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd",
+ .ivlen = 16,
+ },
+ {
+ .cipher = "aes",
+ .mode = "cbc",
+ .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
+ "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+ "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
+ "\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+ .keylen = 32,
+ .ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .plen = 64,
+ .ctext = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba"
+ "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6"
+ "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d"
+ "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d"
+ "\x39\xf2\x33\x69\xa9\xd9\xba\xcf"
+ "\xa5\x30\xe2\x63\x04\x23\x14\x61"
+ "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
+ "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
+ .iv_in = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .iv_out = "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
+ "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
+ .ivlen = 16,
+ },
+};
diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c
index 776934e1f..4214332df 100644
--- a/grub-core/tests/lib/functional_test.c
+++ b/grub-core/tests/lib/functional_test.c
@@ -82,6 +82,7 @@ grub_functional_all_tests (grub_extcmd_context_t ctxt __attribute__ ((unused)),
grub_dl_load ("shift_test");
grub_dl_load ("asn1_test");
grub_dl_load ("argon2_test");
+ grub_dl_load ("crypto_cipher_mode_test");
FOR_LIST_ELEMENTS (test, grub_test_list)
ok = !grub_test_run (test) && ok;
--
2.52.0
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-01-02 6:45 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-02 6:44 [PATCH v3] tests: add functional tests for ecb/cbc helpers Srish Srinivasan
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.