Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/lib/crypto/tests/aes_cbc_macs_kunit.c
170891 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright 2026 Google LLC
4
*/
5
#include <crypto/aes-cbc-macs.h>
6
#include "aes-cmac-testvecs.h"
7
8
/*
9
* A fixed key used when presenting AES-CMAC as an unkeyed hash function in
10
* order to reuse hash-test-template.h. At the beginning of the test suite,
11
* this is initialized to a key prepared from bytes generated from a fixed seed.
12
*/
13
static struct aes_cmac_key test_key;
14
15
static void aes_cmac_init_withtestkey(struct aes_cmac_ctx *ctx)
16
{
17
aes_cmac_init(ctx, &test_key);
18
}
19
20
static void aes_cmac_withtestkey(const u8 *data, size_t data_len,
21
u8 out[AES_BLOCK_SIZE])
22
{
23
aes_cmac(&test_key, data, data_len, out);
24
}
25
26
#define HASH aes_cmac_withtestkey
27
#define HASH_CTX aes_cmac_ctx
28
#define HASH_SIZE AES_BLOCK_SIZE
29
#define HASH_INIT aes_cmac_init_withtestkey
30
#define HASH_UPDATE aes_cmac_update
31
#define HASH_FINAL aes_cmac_final
32
#include "hash-test-template.h"
33
34
static int aes_cbc_macs_suite_init(struct kunit_suite *suite)
35
{
36
u8 raw_key[AES_KEYSIZE_256];
37
int err;
38
39
rand_bytes_seeded_from_len(raw_key, sizeof(raw_key));
40
err = aes_cmac_preparekey(&test_key, raw_key, sizeof(raw_key));
41
if (err)
42
return err;
43
return hash_suite_init(suite);
44
}
45
46
static void aes_cbc_macs_suite_exit(struct kunit_suite *suite)
47
{
48
hash_suite_exit(suite);
49
}
50
51
/* Verify compatibility of the AES-CMAC implementation with RFC 4493. */
52
static void test_aes_cmac_rfc4493(struct kunit *test)
53
{
54
static const u8 raw_key[AES_KEYSIZE_128] = {
55
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
56
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
57
};
58
static const struct {
59
size_t data_len;
60
const u8 data[40];
61
const u8 mac[AES_BLOCK_SIZE];
62
} testvecs[] = {
63
{
64
/* Example 1 from RFC 4493 */
65
.data_len = 0,
66
.mac = {
67
0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
68
0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46,
69
},
70
71
},
72
{
73
/* Example 2 from RFC 4493 */
74
.data = {
75
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
76
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
77
},
78
.data_len = 16,
79
.mac = {
80
0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
81
0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c,
82
},
83
},
84
{
85
/* Example 3 from RFC 4493 */
86
.data = {
87
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
88
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
89
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
90
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
91
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
92
},
93
.data_len = 40,
94
.mac = {
95
0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
96
0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27,
97
},
98
},
99
};
100
struct aes_cmac_key key;
101
int err;
102
103
err = aes_cmac_preparekey(&key, raw_key, sizeof(raw_key));
104
KUNIT_ASSERT_EQ(test, err, 0);
105
106
for (size_t i = 0; i < ARRAY_SIZE(testvecs); i++) {
107
u8 mac[AES_BLOCK_SIZE];
108
109
aes_cmac(&key, testvecs[i].data, testvecs[i].data_len, mac);
110
KUNIT_ASSERT_MEMEQ(test, mac, testvecs[i].mac, AES_BLOCK_SIZE);
111
}
112
}
113
114
/*
115
* Verify compatibility of the AES-XCBC-MAC implementation with RFC 3566.
116
*
117
* Additional AES-XCBC-MAC tests are not necessary, since the AES-XCBC-MAC
118
* implementation is well covered by the AES-CMAC tests already. Only the key
119
* preparation function differs; the rest of the code is shared.
120
*/
121
static void test_aes_xcbcmac_rfc3566(struct kunit *test)
122
{
123
struct aes_cmac_key key;
124
/* AES-XCBC-MAC Test Case #4 from RFC 3566 */
125
static const u8 raw_key[AES_KEYSIZE_128] = {
126
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
127
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
128
};
129
static const u8 message[20] = {
130
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
131
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
132
};
133
static const u8 expected_mac[AES_BLOCK_SIZE] = {
134
0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15,
135
0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08,
136
};
137
u8 actual_mac[AES_BLOCK_SIZE];
138
139
aes_xcbcmac_preparekey(&key, raw_key);
140
aes_cmac(&key, message, sizeof(message), actual_mac);
141
KUNIT_ASSERT_MEMEQ(test, actual_mac, expected_mac, AES_BLOCK_SIZE);
142
}
143
144
static void test_aes_cbcmac_rfc3610(struct kunit *test)
145
{
146
/*
147
* The following AES-CBC-MAC test vector is extracted from RFC 3610
148
* Packet Vector #11. It required some rearrangement to get the actual
149
* input to AES-CBC-MAC from the values given.
150
*/
151
static const u8 raw_key[AES_KEYSIZE_128] = {
152
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
153
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
154
};
155
const size_t unpadded_data_len = 52;
156
static const u8 data[64] = {
157
/* clang-format off */
158
/* CCM header */
159
0x61, 0x00, 0x00, 0x00, 0x0d, 0x0c, 0x0b, 0x0a,
160
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x14,
161
/* CCM additional authentication blocks */
162
0x00, 0x0c, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
163
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00,
164
/* CCM message blocks */
165
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
166
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
167
0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x00, 0x00, 0x00,
168
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169
/* clang-format on */
170
};
171
static const u8 expected_mac[AES_BLOCK_SIZE] = {
172
0x6b, 0x5e, 0x24, 0x34, 0x12, 0xcc, 0xc2, 0xad,
173
0x6f, 0x1b, 0x11, 0xc3, 0xa1, 0xa9, 0xd8, 0xbc,
174
};
175
struct aes_enckey key;
176
struct aes_cbcmac_ctx ctx;
177
u8 actual_mac[AES_BLOCK_SIZE];
178
int err;
179
180
err = aes_prepareenckey(&key, raw_key, sizeof(raw_key));
181
KUNIT_ASSERT_EQ(test, err, 0);
182
183
/*
184
* Trailing zeroes should not affect the CBC-MAC value, up to the next
185
* AES block boundary.
186
*/
187
for (size_t data_len = unpadded_data_len; data_len <= sizeof(data);
188
data_len++) {
189
aes_cbcmac_init(&ctx, &key);
190
aes_cbcmac_update(&ctx, data, data_len);
191
aes_cbcmac_final(&ctx, actual_mac);
192
KUNIT_ASSERT_MEMEQ(test, actual_mac, expected_mac,
193
AES_BLOCK_SIZE);
194
195
/* Incremental computations should produce the same result. */
196
for (size_t part1_len = 0; part1_len <= data_len; part1_len++) {
197
aes_cbcmac_init(&ctx, &key);
198
aes_cbcmac_update(&ctx, data, part1_len);
199
aes_cbcmac_update(&ctx, &data[part1_len],
200
data_len - part1_len);
201
aes_cbcmac_final(&ctx, actual_mac);
202
KUNIT_ASSERT_MEMEQ(test, actual_mac, expected_mac,
203
AES_BLOCK_SIZE);
204
}
205
}
206
}
207
208
static struct kunit_case aes_cbc_macs_test_cases[] = {
209
HASH_KUNIT_CASES,
210
KUNIT_CASE(test_aes_cmac_rfc4493),
211
KUNIT_CASE(test_aes_xcbcmac_rfc3566),
212
KUNIT_CASE(test_aes_cbcmac_rfc3610),
213
KUNIT_CASE(benchmark_hash),
214
{},
215
};
216
217
static struct kunit_suite aes_cbc_macs_test_suite = {
218
.name = "aes_cbc_macs",
219
.test_cases = aes_cbc_macs_test_cases,
220
.suite_init = aes_cbc_macs_suite_init,
221
.suite_exit = aes_cbc_macs_suite_exit,
222
};
223
kunit_test_suite(aes_cbc_macs_test_suite);
224
225
MODULE_DESCRIPTION(
226
"KUnit tests and benchmark for AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC");
227
MODULE_IMPORT_NS("CRYPTO_INTERNAL");
228
MODULE_LICENSE("GPL");
229
230