Skip to content

Commit 51ebc6f

Browse files
ssrish17Daniel Kiper
authored andcommitted
tests: Add functional tests for ecb/cbc helpers
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>
1 parent caaf50b commit 51ebc6f

File tree

5 files changed

+343
-0
lines changed

5 files changed

+343
-0
lines changed

docs/grub.texi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4078,6 +4078,7 @@ Modules can be loaded via the @command{insmod} (@pxref{insmod}) command.
40784078
* cpio_be_module::
40794079
* cpuid_module::
40804080
* crc64_module::
4081+
* crypto_cipher_mode_test_module::
40814082
* crypto_module::
40824083
* cryptodisk_module::
40834084
* cs5536_module::
@@ -4610,6 +4611,10 @@ various CPU features. @xref{cpuid} for more information.
46104611
@section crc64
46114612
This module provides support for the CRC64 operation.
46124613

4614+
@node crypto_cipher_mode_test_module
4615+
@section crypto_cipher_mode_test
4616+
This module performs various cipher mode encryption/decryption tests
4617+
46134618
@node crypto_module
46144619
@section crypto
46154620
This module provides library support for various base cryptography operations

grub-core/Makefile.core.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,11 @@ module = {
22722272
common = tests/argon2_test.c;
22732273
};
22742274

2275+
module = {
2276+
name = crypto_cipher_mode_test;
2277+
common = tests/crypto_cipher_mode_test.c;
2278+
};
2279+
22752280
module = {
22762281
name = legacy_password_test;
22772282
common = tests/legacy_password_test.c;
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* GRUB -- GRand Unified Bootloader
3+
* Copyright (C) 2025 Free Software Foundation, Inc.
4+
*
5+
* GRUB is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* GRUB is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
#include <grub/test.h>
20+
#include <grub/dl.h>
21+
#include <grub/misc.h>
22+
#include <grub/crypto.h>
23+
24+
#include "crypto_cipher_mode_vectors.h"
25+
26+
GRUB_MOD_LICENSE ("GPLv3+");
27+
28+
/* Perform cipher lookup, handle init, and key setting. */
29+
static grub_crypto_cipher_handle_t
30+
handle_init (struct vector vec, grub_crypto_cipher_handle_t handle)
31+
{
32+
gcry_err_code_t err;
33+
34+
const gcry_cipher_spec_t *cipher = grub_crypto_lookup_cipher_by_name (vec.cipher);
35+
grub_test_assert (cipher != NULL, "\n%s: cipher lookup failed for %s", vec.mode, vec.cipher);
36+
if (cipher == NULL)
37+
return NULL;
38+
39+
handle = grub_crypto_cipher_open (cipher);
40+
grub_test_assert (handle != NULL, "\n%s: handle init failed for %s", vec.mode, vec.cipher);
41+
if (handle == NULL)
42+
return NULL;
43+
44+
err = grub_crypto_cipher_set_key (handle, (grub_uint8_t *) vec.key, vec.keylen);
45+
grub_test_assert (err == GPG_ERR_NO_ERROR, "\n%s: key set of size %d failed for %s with err = %d",
46+
vec.mode, vec.keylen, vec.cipher, err);
47+
if (err != GPG_ERR_NO_ERROR)
48+
{
49+
grub_crypto_cipher_close (handle);
50+
return NULL;
51+
}
52+
53+
return handle;
54+
}
55+
56+
static void
57+
ecb_test (struct vector vec)
58+
{
59+
gcry_err_code_t gcry_err;
60+
grub_crypto_cipher_handle_t handle = NULL;
61+
grub_uint8_t *plaintext = NULL, *ciphertext = NULL;
62+
grub_int32_t rc;
63+
64+
handle = handle_init (vec, handle);
65+
if (handle == NULL)
66+
return;
67+
68+
/* Test encryption. */
69+
ciphertext = grub_zalloc (vec.plen);
70+
grub_test_assert (ciphertext != NULL, "\necb: ciphertext buffer allocation failed");
71+
if (ciphertext == NULL)
72+
goto out_handle;
73+
74+
gcry_err = grub_crypto_ecb_encrypt (handle, ciphertext, vec.ptext, vec.plen);
75+
grub_test_assert (gcry_err == GPG_ERR_NO_ERROR, "\necb: encryption failed with err = %d",
76+
gcry_err);
77+
if (gcry_err != GPG_ERR_NO_ERROR)
78+
goto out_ct;
79+
80+
rc = grub_memcmp (ciphertext, vec.ctext, vec.plen);
81+
grub_test_assert (rc == 0, "\necb: ciphertext mismatch after encryption");
82+
if (rc != 0)
83+
goto out_ct;
84+
85+
/* Test decryption. */
86+
plaintext = grub_zalloc (vec.plen);
87+
grub_test_assert (plaintext != NULL, "\necb: plaintext buffer allocation failed");
88+
if (plaintext == NULL)
89+
goto out_ct;
90+
91+
gcry_err = grub_crypto_ecb_decrypt (handle, plaintext, ciphertext, vec.plen);
92+
grub_test_assert (gcry_err == GPG_ERR_NO_ERROR, "\necb: decryption failed failed with err = %d",
93+
gcry_err);
94+
if (gcry_err != GPG_ERR_NO_ERROR)
95+
goto out_pt;
96+
97+
rc = grub_memcmp (plaintext, vec.ptext, vec.plen);
98+
grub_test_assert (rc == 0, "\necb: plaintext mismatch after decryption");
99+
100+
out_pt:
101+
grub_free(plaintext);
102+
out_ct:
103+
grub_free(ciphertext);
104+
out_handle:
105+
grub_crypto_cipher_close(handle);
106+
}
107+
108+
static void
109+
cbc_test (struct vector vec)
110+
{
111+
gcry_err_code_t gcry_err;
112+
grub_crypto_cipher_handle_t handle = NULL;
113+
grub_uint8_t *plaintext = NULL, *ciphertext = NULL;
114+
grub_uint32_t *iv = NULL;
115+
grub_int32_t rc;
116+
117+
handle = handle_init (vec, handle);
118+
if (handle == NULL)
119+
return;
120+
121+
/* Test Encryption */
122+
iv = grub_malloc(vec.ivlen);
123+
grub_test_assert (iv != NULL, "\ncbc: IV buffer allocation failed");
124+
if (iv == NULL)
125+
goto out_handle;
126+
127+
grub_memcpy (iv, vec.iv_in, vec.ivlen);
128+
129+
ciphertext = grub_zalloc (vec.plen);
130+
grub_test_assert (ciphertext != NULL, "\ncbc: ciphertext buffer allocation failed");
131+
if (ciphertext == NULL)
132+
goto out_iv;
133+
134+
gcry_err = grub_crypto_cbc_encrypt (handle, ciphertext, vec.ptext, vec.plen, iv);
135+
grub_test_assert (gcry_err == GPG_ERR_NO_ERROR, "\ncbc: encryption failed with err = %d",
136+
gcry_err);
137+
if (gcry_err != GPG_ERR_NO_ERROR)
138+
goto out_ct;
139+
140+
rc = grub_memcmp (ciphertext, vec.ctext, vec.plen);
141+
grub_test_assert (rc == 0, "\ncbc: ciphertext mismatch after encryption");
142+
if (rc != 0)
143+
goto out_ct;
144+
145+
rc = grub_memcmp (iv, vec.iv_out, vec.ivlen);
146+
grub_test_assert (rc == 0, "\ncbc: IV out mismatch after encryption");
147+
if (rc != 0)
148+
goto out_ct;
149+
150+
/* Test Decryption */
151+
grub_memcpy (iv, vec.iv_in, vec.ivlen);
152+
153+
plaintext = grub_zalloc (vec.plen);
154+
grub_test_assert (plaintext != NULL, "\ncbc: plaintext buffer allocation failed");
155+
if (plaintext == NULL)
156+
goto out_ct;
157+
158+
gcry_err = grub_crypto_cbc_decrypt (handle, plaintext, ciphertext, vec.plen, iv);
159+
grub_test_assert (gcry_err == GPG_ERR_NO_ERROR, "\ncbc: decryption failed with err = %d",
160+
gcry_err);
161+
if (gcry_err != GPG_ERR_NO_ERROR)
162+
goto out_pt;
163+
164+
rc = grub_memcmp (plaintext, vec.ptext, vec.plen);
165+
grub_test_assert (rc == 0, "\ncbc: plaintext mismatch after decryption");
166+
167+
out_pt:
168+
grub_free(plaintext);
169+
out_ct:
170+
grub_free(ciphertext);
171+
out_iv:
172+
grub_free(iv);
173+
out_handle:
174+
grub_crypto_cipher_close(handle);
175+
}
176+
177+
static void
178+
crypto_cipher_mode_test (void)
179+
{
180+
grub_size_t i;
181+
182+
for (i = 0; i < ARRAY_SIZE (vecs); i++)
183+
{
184+
if (grub_strcmp (vecs[i].mode, "ecb") == 0)
185+
ecb_test(vecs[i]);
186+
else if (grub_strcmp (vecs[i].mode, "cbc") == 0)
187+
cbc_test(vecs[i]);
188+
else
189+
{
190+
grub_test_assert(0, "\n%s mode unsupported for testing", vecs[i].mode);
191+
return;
192+
}
193+
}
194+
}
195+
196+
/* Register example_test method as a functional test. */
197+
GRUB_FUNCTIONAL_TEST (crypto_cipher_mode_test, crypto_cipher_mode_test);
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
struct vector
2+
{
3+
const char *cipher;
4+
const char *mode;
5+
const char *key;
6+
grub_uint32_t keylen;
7+
const char *ptext;
8+
grub_uint32_t plen;
9+
const char *ctext;
10+
const char *iv_in;
11+
const char *iv_out;
12+
grub_uint32_t ivlen;
13+
} vecs[] = {
14+
{
15+
.cipher = "aes",
16+
.mode = "ecb",
17+
.key = "\x00\x01\x02\x03\x04\x05\x06\x07"
18+
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
19+
.keylen = 16,
20+
.ptext = "\x00\x11\x22\x33\x44\x55\x66\x77"
21+
"\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
22+
.plen = 16,
23+
.ctext = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
24+
"\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
25+
},
26+
{
27+
.cipher = "aes",
28+
.mode = "ecb",
29+
.key = "\x00\x01\x02\x03\x04\x05\x06\x07"
30+
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
31+
"\x10\x11\x12\x13\x14\x15\x16\x17",
32+
.keylen = 24,
33+
.ptext = "\x00\x11\x22\x33\x44\x55\x66\x77"
34+
"\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
35+
.plen = 16,
36+
.ctext = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
37+
"\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
38+
},
39+
{
40+
.cipher = "aes",
41+
.mode = "ecb",
42+
.key = "\x00\x01\x02\x03\x04\x05\x06\x07"
43+
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
44+
"\x10\x11\x12\x13\x14\x15\x16\x17"
45+
"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
46+
.keylen = 32,
47+
.ptext = "\x00\x11\x22\x33\x44\x55\x66\x77"
48+
"\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
49+
.plen = 16,
50+
.ctext = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
51+
"\xea\xfc\x49\x90\x4b\x49\x60\x89",
52+
},
53+
{
54+
.cipher = "aes",
55+
.mode = "cbc",
56+
.key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
57+
"\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
58+
.keylen = 16,
59+
.ptext = "\x00\x01\x02\x03\x04\x05\x06\x07"
60+
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
61+
"\x10\x11\x12\x13\x14\x15\x16\x17"
62+
"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
63+
.plen = 32,
64+
.ctext = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a"
65+
"\x3a\x86\x30\x28\xb5\xe1\xdc\x0a"
66+
"\x75\x86\x60\x2d\x25\x3c\xff\xf9"
67+
"\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1",
68+
.iv_in = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
69+
"\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
70+
.iv_out = "\x75\x86\x60\x2d\x25\x3c\xff\xf9"
71+
"\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1",
72+
.ivlen = 16,
73+
},
74+
{
75+
.cipher = "aes",
76+
.mode = "cbc",
77+
.key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
78+
"\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
79+
"\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
80+
.keylen = 24,
81+
.ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
82+
"\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
83+
"\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
84+
"\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
85+
"\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
86+
"\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
87+
"\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
88+
"\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
89+
.plen = 64,
90+
.ctext = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d"
91+
"\x71\x78\x18\x3a\x9f\xa0\x71\xe8"
92+
"\xb4\xd9\xad\xa9\xad\x7d\xed\xf4"
93+
"\xe5\xe7\x38\x76\x3f\x69\x14\x5a"
94+
"\x57\x1b\x24\x20\x12\xfb\x7a\xe0"
95+
"\x7f\xa9\xba\xac\x3d\xf1\x02\xe0"
96+
"\x08\xb0\xe2\x79\x88\x59\x88\x81"
97+
"\xd9\x20\xa9\xe6\x4f\x56\x15\xcd",
98+
.iv_in = "\x00\x01\x02\x03\x04\x05\x06\x07"
99+
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
100+
.iv_out = "\x08\xb0\xe2\x79\x88\x59\x88\x81"
101+
"\xd9\x20\xa9\xe6\x4f\x56\x15\xcd",
102+
.ivlen = 16,
103+
},
104+
{
105+
.cipher = "aes",
106+
.mode = "cbc",
107+
.key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
108+
"\x2b\x73\xae\xf0\x85\x7d\x77\x81"
109+
"\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
110+
"\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
111+
.keylen = 32,
112+
.ptext = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
113+
"\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
114+
"\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
115+
"\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
116+
"\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
117+
"\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
118+
"\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
119+
"\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
120+
.plen = 64,
121+
.ctext = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba"
122+
"\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6"
123+
"\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d"
124+
"\x67\x9f\x77\x7b\xc6\x70\x2c\x7d"
125+
"\x39\xf2\x33\x69\xa9\xd9\xba\xcf"
126+
"\xa5\x30\xe2\x63\x04\x23\x14\x61"
127+
"\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
128+
"\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
129+
.iv_in = "\x00\x01\x02\x03\x04\x05\x06\x07"
130+
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
131+
.iv_out = "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
132+
"\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
133+
.ivlen = 16,
134+
},
135+
};

grub-core/tests/lib/functional_test.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ grub_functional_all_tests (grub_extcmd_context_t ctxt __attribute__ ((unused)),
8282
grub_dl_load ("shift_test");
8383
grub_dl_load ("asn1_test");
8484
grub_dl_load ("argon2_test");
85+
grub_dl_load ("crypto_cipher_mode_test");
8586

8687
FOR_LIST_ELEMENTS (test, grub_test_list)
8788
ok = !grub_test_run (test) && ok;

0 commit comments

Comments
 (0)