public inbox for grub-devel@gnu.org
 help / color / mirror / Atom feed
* [PATCH v2] tests: add functional tests for ecb/cbc helpers
@ 2025-12-08  8:28 Srish Srinivasan
  2025-12-19  7:08 ` Sudhakar Kuppusamy
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Srish Srinivasan @ 2025-12-08  8:28 UTC (permalink / raw)
  To: grub-devel; +Cc: daniel.kiper, stefanb, 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>
---
 Link to v1: https://lists.gnu.org/archive/html/grub-devel/2025-11/msg00237.html
 docs/grub.texi                        |   5 +
 grub-core/Makefile.core.def           |   5 +
 grub-core/tests/ecb_cbc_test.c        | 197 ++++++++++++++++++++++++++
 grub-core/tests/ecb_cbc_vectors.h     | 135 ++++++++++++++++++
 grub-core/tests/lib/functional_test.c |   1 +
 5 files changed, 343 insertions(+)
 create mode 100644 grub-core/tests/ecb_cbc_test.c
 create mode 100644 grub-core/tests/ecb_cbc_vectors.h

diff --git a/docs/grub.texi b/docs/grub.texi
index 7181009b6..63a82bba2 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::
+* ecb_cbc_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 ecb_cbc_test_module
+@section ecb_cbc_test
+This module is intended for performing functional tests for ecb and cbc
+
 @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..a28de3a93 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 = ecb_cbc_test;
+  common = tests/ecb_cbc_test.c;
+};
+
 module = {
   name = legacy_password_test;
   common = tests/legacy_password_test.c;
diff --git a/grub-core/tests/ecb_cbc_test.c b/grub-core/tests/ecb_cbc_test.c
new file mode 100644
index 000000000..e988ab224
--- /dev/null
+++ b/grub-core/tests/ecb_cbc_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 "ecb_cbc_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
+ecb_cbc_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 (ecb_cbc_test, ecb_cbc_test);
diff --git a/grub-core/tests/ecb_cbc_vectors.h b/grub-core/tests/ecb_cbc_vectors.h
new file mode 100644
index 000000000..8ef948b46
--- /dev/null
+++ b/grub-core/tests/ecb_cbc_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..84ef95bbe 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 ("ecb_cbc_test");
 
   FOR_LIST_ELEMENTS (test, grub_test_list)
     ok = !grub_test_run (test) && ok;
-- 
2.43.0


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] tests: add functional tests for ecb/cbc helpers
  2025-12-08  8:28 [PATCH v2] tests: add functional tests for ecb/cbc helpers Srish Srinivasan
@ 2025-12-19  7:08 ` Sudhakar Kuppusamy
  2025-12-29 16:06 ` Daniel Kiper
  2026-01-02  5:14 ` Glenn Washburn
  2 siblings, 0 replies; 6+ messages in thread
From: Sudhakar Kuppusamy @ 2025-12-19  7:08 UTC (permalink / raw)
  To: Srish Srinivasan; +Cc: grub-devel, daniel.kiper, stefanb, sridharm



> On 8 Dec 2025, at 1:58 PM, Srish Srinivasan <ssrish@linux.ibm.com> wrote:
> 
> 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>

Thanks,
Sudhakar  
> ---
> Link to v1: https://lists.gnu.org/archive/html/grub-devel/2025-11/msg00237.html
> docs/grub.texi                        |   5 +
> grub-core/Makefile.core.def           |   5 +
> grub-core/tests/ecb_cbc_test.c        | 197 ++++++++++++++++++++++++++
> grub-core/tests/ecb_cbc_vectors.h     | 135 ++++++++++++++++++
> grub-core/tests/lib/functional_test.c |   1 +
> 5 files changed, 343 insertions(+)
> create mode 100644 grub-core/tests/ecb_cbc_test.c
> create mode 100644 grub-core/tests/ecb_cbc_vectors.h
> 
> diff --git a/docs/grub.texi b/docs/grub.texi
> index 7181009b6..63a82bba2 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::
> +* ecb_cbc_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 ecb_cbc_test_module
> +@section ecb_cbc_test
> +This module is intended for performing functional tests for ecb and cbc
> +
> @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..a28de3a93 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 = ecb_cbc_test;
> +  common = tests/ecb_cbc_test.c;
> +};
> +
> module = {
>   name = legacy_password_test;
>   common = tests/legacy_password_test.c;
> diff --git a/grub-core/tests/ecb_cbc_test.c b/grub-core/tests/ecb_cbc_test.c
> new file mode 100644
> index 000000000..e988ab224
> --- /dev/null
> +++ b/grub-core/tests/ecb_cbc_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 "ecb_cbc_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
> +ecb_cbc_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 (ecb_cbc_test, ecb_cbc_test);
> diff --git a/grub-core/tests/ecb_cbc_vectors.h b/grub-core/tests/ecb_cbc_vectors.h
> new file mode 100644
> index 000000000..8ef948b46
> --- /dev/null
> +++ b/grub-core/tests/ecb_cbc_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..84ef95bbe 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 ("ecb_cbc_test");
> 
>   FOR_LIST_ELEMENTS (test, grub_test_list)
>     ok = !grub_test_run (test) && ok;
> -- 
> 2.43.0
> 


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] tests: add functional tests for ecb/cbc helpers
  2025-12-08  8:28 [PATCH v2] tests: add functional tests for ecb/cbc helpers Srish Srinivasan
  2025-12-19  7:08 ` Sudhakar Kuppusamy
@ 2025-12-29 16:06 ` Daniel Kiper
  2026-01-02  5:14 ` Glenn Washburn
  2 siblings, 0 replies; 6+ messages in thread
From: Daniel Kiper @ 2025-12-29 16:06 UTC (permalink / raw)
  To: Srish Srinivasan; +Cc: grub-devel, stefanb, sudhakar, sridharm, development

Adding Glenn...

On Mon, Dec 08, 2025 at 01:58:16PM +0530, Srish Srinivasan wrote:
> 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: Daniel Kiper <daniel.kiper@oracle.com>

Daniel

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] tests: add functional tests for ecb/cbc helpers
  2025-12-08  8:28 [PATCH v2] tests: add functional tests for ecb/cbc helpers Srish Srinivasan
  2025-12-19  7:08 ` Sudhakar Kuppusamy
  2025-12-29 16:06 ` Daniel Kiper
@ 2026-01-02  5:14 ` Glenn Washburn
  2026-01-02  5:37   ` Srish Srinivasan
  2026-01-02  5:39   ` Srish Srinivasan
  2 siblings, 2 replies; 6+ messages in thread
From: Glenn Washburn @ 2026-01-02  5:14 UTC (permalink / raw)
  To: Srish Srinivasan
  Cc: The development of GNU GRUB, daniel.kiper, stefanb, sudhakar,
	sridharm

On Mon,  8 Dec 2025 13:58:16 +0530
Srish Srinivasan <ssrish@linux.ibm.com> wrote:

> 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>
> ---
>  Link to v1: https://lists.gnu.org/archive/html/grub-devel/2025-11/msg00237.html
>  docs/grub.texi                        |   5 +
>  grub-core/Makefile.core.def           |   5 +
>  grub-core/tests/ecb_cbc_test.c        | 197 ++++++++++++++++++++++++++

I would prefer it be named more generally so the
name still makes sense when/if different cipher mode tests are added,
perhaps crypto_cipher_mode_test.c.

>  grub-core/tests/ecb_cbc_vectors.h     | 135 ++++++++++++++++++
>  grub-core/tests/lib/functional_test.c |   1 +
>  5 files changed, 343 insertions(+)
>  create mode 100644 grub-core/tests/ecb_cbc_test.c
>  create mode 100644 grub-core/tests/ecb_cbc_vectors.h
> 
> diff --git a/docs/grub.texi b/docs/grub.texi
> index 7181009b6..63a82bba2 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::
> +* ecb_cbc_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 ecb_cbc_test_module
> +@section ecb_cbc_test
> +This module is intended for performing functional tests for ecb and cbc

This is a bit cryptic (cbc ?= Canadian Broadcasting Corporation). If we
change the name of the module and file, I think we could put: "This
module performs various cipher mode encryption/decryption tests".

It would be nice to have more tests of crypto functions, like
grub_crypto_hash. But that can be for another time.

Other than the above,
Reviewed-by: Glenn Washburn <development@efficientek.com>

Glenn

> +
>  @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..a28de3a93 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 = ecb_cbc_test;
> +  common = tests/ecb_cbc_test.c;
> +};
> +
>  module = {
>    name = legacy_password_test;
>    common = tests/legacy_password_test.c;
> diff --git a/grub-core/tests/ecb_cbc_test.c b/grub-core/tests/ecb_cbc_test.c
> new file mode 100644
> index 000000000..e988ab224
> --- /dev/null
> +++ b/grub-core/tests/ecb_cbc_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 "ecb_cbc_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
> +ecb_cbc_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 (ecb_cbc_test, ecb_cbc_test);
> diff --git a/grub-core/tests/ecb_cbc_vectors.h b/grub-core/tests/ecb_cbc_vectors.h
> new file mode 100644
> index 000000000..8ef948b46
> --- /dev/null
> +++ b/grub-core/tests/ecb_cbc_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..84ef95bbe 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 ("ecb_cbc_test");
>  
>    FOR_LIST_ELEMENTS (test, grub_test_list)
>      ok = !grub_test_run (test) && ok;

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] tests: add functional tests for ecb/cbc helpers
  2026-01-02  5:14 ` Glenn Washburn
@ 2026-01-02  5:37   ` Srish Srinivasan
  2026-01-02  5:39   ` Srish Srinivasan
  1 sibling, 0 replies; 6+ messages in thread
From: Srish Srinivasan @ 2026-01-02  5:37 UTC (permalink / raw)
  To: The development of GNU GRUB, Glenn Washburn
  Cc: daniel.kiper, stefanb, sudhakar, sridharm

Hi Glenn,
thanks for taking a look.

On 1/2/26 10:44 AM, Glenn Washburn wrote:
> On Mon,  8 Dec 2025 13:58:16 +0530
> Srish Srinivasan <ssrish@linux.ibm.com> wrote:
>
>> 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>
>> ---
>>   Link to v1: https://lists.gnu.org/archive/html/grub-devel/2025-11/msg00237.html
>>   docs/grub.texi                        |   5 +
>>   grub-core/Makefile.core.def           |   5 +
>>   grub-core/tests/ecb_cbc_test.c        | 197 ++++++++++++++++++++++++++
> I would prefer it be named more generally so the
> name still makes sense when/if different cipher mode tests are added,
> perhaps crypto_cipher_mode_test.c.


Sure, I will make the change.


>
>>   grub-core/tests/ecb_cbc_vectors.h     | 135 ++++++++++++++++++
>>   grub-core/tests/lib/functional_test.c |   1 +
>>   5 files changed, 343 insertions(+)
>>   create mode 100644 grub-core/tests/ecb_cbc_test.c
>>   create mode 100644 grub-core/tests/ecb_cbc_vectors.h
>>
>> diff --git a/docs/grub.texi b/docs/grub.texi
>> index 7181009b6..63a82bba2 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::
>> +* ecb_cbc_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 ecb_cbc_test_module
>> +@section ecb_cbc_test
>> +This module is intended for performing functional tests for ecb and cbc
> This is a bit cryptic (cbc ?= Canadian Broadcasting Corporation). If we
> change the name of the module and file, I think we could put: "This
> module performs various cipher mode encryption/decryption tests".

Sure, I will keep the file naming and the description more generic
as per your suggestion.

>
> It would be nice to have more tests of crypto functions, like
> grub_crypto_hash. But that can be for another time.
>
> Other than the above,
> Reviewed-by: Glenn Washburn <development@efficientek.com>


Thanks for the review and feedback.
I will send out v3 with these changes shortly.


>
> Glenn
>
>> +
>>   @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..a28de3a93 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 = ecb_cbc_test;
>> +  common = tests/ecb_cbc_test.c;
>> +};
>> +
>>   module = {
>>     name = legacy_password_test;
>>     common = tests/legacy_password_test.c;
>> diff --git a/grub-core/tests/ecb_cbc_test.c b/grub-core/tests/ecb_cbc_test.c
>> new file mode 100644
>> index 000000000..e988ab224
>> --- /dev/null
>> +++ b/grub-core/tests/ecb_cbc_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 "ecb_cbc_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
>> +ecb_cbc_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 (ecb_cbc_test, ecb_cbc_test);
>> diff --git a/grub-core/tests/ecb_cbc_vectors.h b/grub-core/tests/ecb_cbc_vectors.h
>> new file mode 100644
>> index 000000000..8ef948b46
>> --- /dev/null
>> +++ b/grub-core/tests/ecb_cbc_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..84ef95bbe 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 ("ecb_cbc_test");
>>   
>>     FOR_LIST_ELEMENTS (test, grub_test_list)
>>       ok = !grub_test_run (test) && ok;
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel

thanks,
Srish.

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] tests: add functional tests for ecb/cbc helpers
  2026-01-02  5:14 ` Glenn Washburn
  2026-01-02  5:37   ` Srish Srinivasan
@ 2026-01-02  5:39   ` Srish Srinivasan
  1 sibling, 0 replies; 6+ messages in thread
From: Srish Srinivasan @ 2026-01-02  5:39 UTC (permalink / raw)
  To: The development of GNU GRUB, Glenn Washburn
  Cc: daniel.kiper, stefanb, sudhakar, sridharm

Hi Glenn,
thanks for taking a look.

On 1/2/26 10:44 AM, Glenn Washburn wrote:
> On Mon,  8 Dec 2025 13:58:16 +0530
> Srish Srinivasan <ssrish@linux.ibm.com> wrote:
>
>> 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>
>> ---
>>   Link to v1: https://lists.gnu.org/archive/html/grub-devel/2025-11/msg00237.html
>>   docs/grub.texi                        |   5 +
>>   grub-core/Makefile.core.def           |   5 +
>>   grub-core/tests/ecb_cbc_test.c        | 197 ++++++++++++++++++++++++++
> I would prefer it be named more generally so the
> name still makes sense when/if different cipher mode tests are added,
> perhaps crypto_cipher_mode_test.c.


Sure, I will make the change.


>
>>   grub-core/tests/ecb_cbc_vectors.h     | 135 ++++++++++++++++++
>>   grub-core/tests/lib/functional_test.c |   1 +
>>   5 files changed, 343 insertions(+)
>>   create mode 100644 grub-core/tests/ecb_cbc_test.c
>>   create mode 100644 grub-core/tests/ecb_cbc_vectors.h
>>
>> diff --git a/docs/grub.texi b/docs/grub.texi
>> index 7181009b6..63a82bba2 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::
>> +* ecb_cbc_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 ecb_cbc_test_module
>> +@section ecb_cbc_test
>> +This module is intended for performing functional tests for ecb and cbc
> This is a bit cryptic (cbc ?= Canadian Broadcasting Corporation). If we
> change the name of the module and file, I think we could put: "This
> module performs various cipher mode encryption/decryption tests".

Sure, I will keep the file naming and the description more generic
as per your suggestion.

>
> It would be nice to have more tests of crypto functions, like
> grub_crypto_hash. But that can be for another time.
>
> Other than the above,
> Reviewed-by: Glenn Washburn <development@efficientek.com>


Thanks for the review and feedback.
I will send out v3 with these changes shortly.


>
> Glenn
>
>> +
>>   @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..a28de3a93 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 = ecb_cbc_test;
>> +  common = tests/ecb_cbc_test.c;
>> +};
>> +
>>   module = {
>>     name = legacy_password_test;
>>     common = tests/legacy_password_test.c;
>> diff --git a/grub-core/tests/ecb_cbc_test.c b/grub-core/tests/ecb_cbc_test.c
>> new file mode 100644
>> index 000000000..e988ab224
>> --- /dev/null
>> +++ b/grub-core/tests/ecb_cbc_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 "ecb_cbc_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
>> +ecb_cbc_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 (ecb_cbc_test, ecb_cbc_test);
>> diff --git a/grub-core/tests/ecb_cbc_vectors.h b/grub-core/tests/ecb_cbc_vectors.h
>> new file mode 100644
>> index 000000000..8ef948b46
>> --- /dev/null
>> +++ b/grub-core/tests/ecb_cbc_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..84ef95bbe 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 ("ecb_cbc_test");
>>   
>>     FOR_LIST_ELEMENTS (test, grub_test_list)
>>       ok = !grub_test_run (test) && ok;
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel

thanks,
Srish.

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-01-02  5:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-08  8:28 [PATCH v2] tests: add functional tests for ecb/cbc helpers Srish Srinivasan
2025-12-19  7:08 ` Sudhakar Kuppusamy
2025-12-29 16:06 ` Daniel Kiper
2026-01-02  5:14 ` Glenn Washburn
2026-01-02  5:37   ` Srish Srinivasan
2026-01-02  5:39   ` Srish Srinivasan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox