History

lib/crypto: tests: Add KUnit test suite for AES-GCM

Add a KUnit test suite for the AES-GCM library API. It consists of: - All the shared test cases from aead-test-template.h. These include extensive consistency tests, a "Monte-Carlo test", and a benchmark. - Tests against hardcoded AES-GCM test vectors from external sources.

Eric Biggers committed 3 months ago

Commit b09bd2d1 parent 2aeef505 files · +494 −2Browse files

Unified · Split

5 files
  1. lib/crypto/.kunitconfig +1 −0
  2. lib/crypto/tests/Kconfig +9 −0
  3. lib/crypto/tests/Makefile +1 −0
  4. lib/crypto/tests/aes_gcm_kunit.c +472 −0
  5. scripts/crypto/gen-aead-testvecs.py +11 −2
lib/crypto/.kunitconfig+1−0
@@ -4,6 +4,7 @@ CONFIG_CRYPTO_LIB_ENABLE_ALL_FOR_KUNIT=y · 3 unmodified lines
4 4
5CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST=y5CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST=y
6CONFIG_CRYPTO_LIB_AES_CCM_KUNIT_TEST=y6CONFIG_CRYPTO_LIB_AES_CCM_KUNIT_TEST=y
7CONFIG_CRYPTO_LIB_AES_GCM_KUNIT_TEST=y
7CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST=y8CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST=y
8CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST=y9CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST=y
9CONFIG_CRYPTO_LIB_CHACHA20POLY1305_KUNIT_TEST=y10CONFIG_CRYPTO_LIB_CHACHA20POLY1305_KUNIT_TEST=y
lib/crypto/tests/Kconfig+9−0
@@ -18,6 +18,15 @@ config CRYPTO_LIB_AES_CCM_KUNIT_TEST · 17 unmodified lines
18 help18 help
19 KUnit tests for the AES-CCM authenticated encryption algorithm.19 KUnit tests for the AES-CCM authenticated encryption algorithm.
20 20
21config CRYPTO_LIB_AES_GCM_KUNIT_TEST
22 tristate "KUnit tests for AES-GCM" if !KUNIT_ALL_TESTS
23 depends on KUNIT && CRYPTO_LIB_AES_GCM
24 default KUNIT_ALL_TESTS
25 select CRYPTO_LIB_BENCHMARK_VISIBLE
26 # This test uses BLAKE2s, but that's always built-in.
27 help
28 KUnit tests for the AES-GCM authenticated encryption algorithm.
29
21config CRYPTO_LIB_BLAKE2B_KUNIT_TEST30config CRYPTO_LIB_BLAKE2B_KUNIT_TEST
22 tristate "KUnit tests for BLAKE2b" if !KUNIT_ALL_TESTS31 tristate "KUnit tests for BLAKE2b" if !KUNIT_ALL_TESTS
23 depends on KUNIT && CRYPTO_LIB_BLAKE2B32 depends on KUNIT && CRYPTO_LIB_BLAKE2B
lib/crypto/tests/Makefile+1−0
@@ -2,6 +2,7 @@ · 1 unmodified line
2 2
3obj-$(CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST) += aes_cbc_macs_kunit.o3obj-$(CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST) += aes_cbc_macs_kunit.o
4obj-$(CONFIG_CRYPTO_LIB_AES_CCM_KUNIT_TEST) += aes_ccm_kunit.o4obj-$(CONFIG_CRYPTO_LIB_AES_CCM_KUNIT_TEST) += aes_ccm_kunit.o
5obj-$(CONFIG_CRYPTO_LIB_AES_GCM_KUNIT_TEST) += aes_gcm_kunit.o
5obj-$(CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST) += blake2b_kunit.o6obj-$(CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST) += blake2b_kunit.o
6obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o7obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o
7obj-$(CONFIG_CRYPTO_LIB_CHACHA20POLY1305_KUNIT_TEST) += chacha20poly1305_kunit.o8obj-$(CONFIG_CRYPTO_LIB_CHACHA20POLY1305_KUNIT_TEST) += chacha20poly1305_kunit.o
lib/crypto/tests/aes_gcm_kunit.c+472−0
@@ -0,0 +1,472 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * KUnit test suite for AES-GCM
4 *
5 * Copyright 2026 Google LLC
6 */
7#include <crypto/aes-gcm.h>
8#include <crypto/blake2s.h>
9#include "test-utils.h"
10
11/* The kernel's AES-GCM implementation supports only 12-byte nonces. */
12#define AES_GCM_NONCE_LEN 12
13
14/*
15 * AES-GCM test vectors from the original paper "The Galois/Counter Mode of
16 * Operation (GCM)" by McGrew & Viega. Vectors with nonce lengths other than 12
17 * bytes are excluded.
18 */
19static const struct aes_gcm_testvec {
20 const char *name;
21 const char *key;
22 size_t key_len;
23 const char *nonce;
24 size_t nonce_len;
25 const char *ad;
26 size_t ad_len;
27 const char *ptext;
28 const char *ctext;
29 size_t data_len;
30 const char *tag;
31 size_t tag_len;
32} aes_gcm_testvecs[] = {
33 /* AES-128 Test Vectors */
34 {
35 .name = "McGrew & Viega Test Case 1",
36 .key = "\x00\x00\x00\x00\x00\x00\x00\x00"
37 "\x00\x00\x00\x00\x00\x00\x00\x00",
38 .key_len = 16,
39 .nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
40 "\x00\x00\x00\x00",
41 .nonce_len = 12,
42 .ptext = "",
43 .ctext = "",
44 .data_len = 0,
45 .ad = "",
46 .ad_len = 0,
47 .tag = "\x58\xe2\xfc\xce\xfa\x7e\x30\x61"
48 "\x36\x7f\x1d\x57\xa4\xe7\x45\x5a",
49 .tag_len = 16,
50 },
51 {
52 .name = "McGrew & Viega Test Case 2",
53 .key = "\x00\x00\x00\x00\x00\x00\x00\x00"
54 "\x00\x00\x00\x00\x00\x00\x00\x00",
55 .key_len = 16,
56 .nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
57 "\x00\x00\x00\x00",
58 .nonce_len = 12,
59 .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00"
60 "\x00\x00\x00\x00\x00\x00\x00\x00",
61 .ctext = "\x03\x88\xda\xce\x60\xb6\xa3\x92"
62 "\xf3\x28\xc2\xb9\x71\xb2\xfe\x78",
63 .data_len = 16,
64 .ad = "",
65 .ad_len = 0,
66 .tag = "\xab\x6e\x47\xd4\x2c\xec\x13\xbd"
67 "\xf5\x3a\x67\xb2\x12\x57\xbd\xdf",
68 .tag_len = 16,
69 },
70 {
71 .name = "McGrew & Viega Test Case 3",
72 .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
73 "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
74 .key_len = 16,
75 .nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
76 "\xde\xca\xf8\x88",
77 .nonce_len = 12,
78 .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
79 "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
80 "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
81 "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
82 "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
83 "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
84 "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
85 "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
86 .ctext = "\x42\x83\x1e\xc2\x21\x77\x74\x24"
87 "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
88 "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
89 "\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
90 "\x21\xd5\x14\xb2\x54\x66\x93\x1c"
91 "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
92 "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
93 "\x3d\x58\xe0\x91\x47\x3f\x59\x85",
94 .data_len = 64,
95 .ad = "",
96 .ad_len = 0,
97 .tag = "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6"
98 "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4",
99 .tag_len = 16,
100 },
101 {
102 .name = "McGrew & Viega Test Case 4",
103 .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
104 "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
105 .key_len = 16,
106 .nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
107 "\xde\xca\xf8\x88",
108 .nonce_len = 12,
109 .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
110 "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
111 "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
112 "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
113 "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
114 "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
115 "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
116 "\xba\x63\x7b\x39",
117 .ctext = "\x42\x83\x1e\xc2\x21\x77\x74\x24"
118 "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
119 "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
120 "\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
121 "\x21\xd5\x14\xb2\x54\x66\x93\x1c"
122 "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
123 "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
124 "\x3d\x58\xe0\x91",
125 .data_len = 60,
126 .ad = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
127 "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
128 "\xab\xad\xda\xd2",
129 .ad_len = 20,
130 .tag = "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb"
131 "\x94\xfa\xe9\x5a\xe7\x12\x1a\x47",
132 .tag_len = 16,
133 },
134
135 /* AES-192 Test Vectors */
136 {
137 .name = "McGrew & Viega Test Case 7",
138 .key = "\x00\x00\x00\x00\x00\x00\x00\x00"
139 "\x00\x00\x00\x00\x00\x00\x00\x00"
140 "\x00\x00\x00\x00\x00\x00\x00\x00",
141 .key_len = 24,
142 .nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
143 "\x00\x00\x00\x00",
144 .nonce_len = 12,
145 .ptext = "",
146 .ctext = "",
147 .data_len = 0,
148 .ad = "",
149 .ad_len = 0,
150 .tag = "\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b"
151 "\xa0\x0e\xd1\xf3\x12\x57\x24\x35",
152 .tag_len = 16,
153 },
154 {
155 .name = "McGrew & Viega Test Case 8",
156 .key = "\x00\x00\x00\x00\x00\x00\x00\x00"
157 "\x00\x00\x00\x00\x00\x00\x00\x00"
158 "\x00\x00\x00\x00\x00\x00\x00\x00",
159 .key_len = 24,
160 .nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
161 "\x00\x00\x00\x00",
162 .nonce_len = 12,
163 .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00"
164 "\x00\x00\x00\x00\x00\x00\x00\x00",
165 .ctext = "\x98\xe7\x24\x7c\x07\xf0\xfe\x41"
166 "\x1c\x26\x7e\x43\x84\xb0\xf6\x00",
167 .data_len = 16,
168 .ad = "",
169 .ad_len = 0,
170 .tag = "\x2f\xf5\x8d\x80\x03\x39\x27\xab"
171 "\x8e\xf4\xd4\x58\x75\x14\xf0\xfb",
172 .tag_len = 16,
173 },
174 {
175 .name = "McGrew & Viega Test Case 9",
176 .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
177 "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
178 "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
179 .key_len = 24,
180 .nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
181 "\xde\xca\xf8\x88",
182 .nonce_len = 12,
183 .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
184 "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
185 "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
186 "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
187 "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
188 "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
189 "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
190 "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
191 .ctext = "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
192 "\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
193 "\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
194 "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
195 "\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
196 "\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
197 "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
198 "\xcc\xda\x27\x10\xac\xad\xe2\x56",
199 .data_len = 64,
200 .ad = "",
201 .ad_len = 0,
202 .tag = "\x99\x24\xa7\xc8\x58\x73\x36\xbf"
203 "\xb1\x18\x02\x4d\xb8\x67\x4a\x14",
204 .tag_len = 16,
205 },
206 {
207 .name = "McGrew & Viega Test Case 10",
208 .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
209 "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
210 "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
211 .key_len = 24,
212 .nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
213 "\xde\xca\xf8\x88",
214 .nonce_len = 12,
215 .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
216 "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
217 "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
218 "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
219 "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
220 "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
221 "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
222 "\xba\x63\x7b\x39",
223 .ctext = "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
224 "\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
225 "\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
226 "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
227 "\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
228 "\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
229 "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
230 "\xcc\xda\x27\x10",
231 .data_len = 60,
232 .ad = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
233 "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
234 "\xab\xad\xda\xd2",
235 .ad_len = 20,
236 .tag = "\x25\x19\x49\x8e\x80\xf1\x47\x8f"
237 "\x37\xba\x55\xbd\x6d\x27\x61\x8c",
238 .tag_len = 16,
239 },
240
241 /* AES-256 Test Vectors */
242 {
243 .name = "McGrew & Viega Test Case 13",
244 .key = "\x00\x00\x00\x00\x00\x00\x00\x00"
245 "\x00\x00\x00\x00\x00\x00\x00\x00"
246 "\x00\x00\x00\x00\x00\x00\x00\x00"
247 "\x00\x00\x00\x00\x00\x00\x00\x00",
248 .key_len = 32,
249 .nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
250 "\x00\x00\x00\x00",
251 .nonce_len = 12,
252 .ptext = "",
253 .ctext = "",
254 .data_len = 0,
255 .ad = "",
256 .ad_len = 0,
257 .tag = "\x53\x0f\x8a\xfb\xc7\x45\x36\xb9"
258 "\xa9\x63\xb4\xf1\xc4\xcb\x73\x8b",
259 .tag_len = 16,
260 },
261 {
262 .name = "McGrew & Viega Test Case 14",
263 .key = "\x00\x00\x00\x00\x00\x00\x00\x00"
264 "\x00\x00\x00\x00\x00\x00\x00\x00"
265 "\x00\x00\x00\x00\x00\x00\x00\x00"
266 "\x00\x00\x00\x00\x00\x00\x00\x00",
267 .key_len = 32,
268 .nonce = "\x00\x00\x00\x00\x00\x00\x00\x00"
269 "\x00\x00\x00\x00",
270 .nonce_len = 12,
271 .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00"
272 "\x00\x00\x00\x00\x00\x00\x00\x00",
273 .ctext = "\xce\xa7\x40\x3d\x4d\x60\x6b\x6e"
274 "\x07\x4e\xc5\xd3\xba\xf3\x9d\x18",
275 .data_len = 16,
276 .ad = "",
277 .ad_len = 0,
278 .tag = "\xd0\xd1\xc8\xa7\x99\x99\x6b\xf0"
279 "\x26\x5b\x98\xb5\xd4\x8a\xb9\x19",
280 .tag_len = 16,
281 },
282 {
283 .name = "McGrew & Viega Test Case 15",
284 .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
285 "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
286 "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
287 "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
288 .key_len = 32,
289 .nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
290 "\xde\xca\xf8\x88",
291 .nonce_len = 12,
292 .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
293 "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
294 "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
295 "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
296 "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
297 "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
298 "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
299 "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
300 .ctext = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
301 "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
302 "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
303 "\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
304 "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d"
305 "\xa7\xb0\x8b\x10\x56\x82\x88\x38"
306 "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a"
307 "\xbc\xc9\xf6\x62\x89\x80\x15\xad",
308 .data_len = 64,
309 .ad = "",
310 .ad_len = 0,
311 .tag = "\xb0\x94\xda\xc5\xd9\x34\x71\xbd"
312 "\xec\x1a\x50\x22\x70\xe3\xcc\x6c",
313 .tag_len = 16,
314 },
315 {
316 .name = "McGrew & Viega Test Case 16",
317 .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
318 "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
319 "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
320 "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
321 .key_len = 32,
322 .nonce = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
323 "\xde\xca\xf8\x88",
324 .nonce_len = 12,
325 .ptext = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
326 "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
327 "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
328 "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
329 "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
330 "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
331 "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
332 "\xba\x63\x7b\x39",
333 .ctext = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
334 "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
335 "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
336 "\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
337 "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d"
338 "\xa7\xb0\x8b\x10\x56\x82\x88\x38"
339 "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a"
340 "\xbc\xc9\xf6\x62",
341 .data_len = 60,
342 .ad = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
343 "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
344 "\xab\xad\xda\xd2",
345 .ad_len = 20,
346 .tag = "\x76\xfc\x6e\xce\x0f\x4e\x17\x68"
347 "\xcd\xdf\x88\x53\xbb\x2d\x55\x1b",
348 .tag_len = 16,
349 },
350};
351
352static void test_aes_gcm_one_test_vector(struct kunit *test,
353 const struct aes_gcm_testvec *tv)
354{
355 u8 *ctext = alloc_buf(test, tv->data_len);
356 u8 *decrypted = alloc_buf(test, tv->data_len);
357 u8 *tag = alloc_buf(test, tv->tag_len);
358 struct aes_gcm_key key;
359 int err;
360
361 KUNIT_ASSERT_EQ(test, AES_GCM_NONCE_LEN, tv->nonce_len);
362
363 err = aes_gcm_preparekey(&key, tv->key, tv->key_len, tv->tag_len);
364 KUNIT_ASSERT_EQ_MSG(test, 0, err, "Failed to prepare key for %s",
365 tv->name);
366
367 aes_gcm_encrypt(ctext, tv->ptext, tv->data_len, tag, tv->ad, tv->ad_len,
368 tv->nonce, &key);
369 KUNIT_ASSERT_MEMEQ_MSG(test, tv->ctext, ctext, tv->data_len,
370 "Wrong ciphertext for %s", tv->name);
371 KUNIT_ASSERT_MEMEQ_MSG(test, tag, tv->tag, tv->tag_len,
372 "Wrong tag for %s", tv->name);
373
374 err = aes_gcm_decrypt(decrypted, ctext, tv->data_len, tag, tv->ad,
375 tv->ad_len, tv->nonce, &key);
376 KUNIT_ASSERT_EQ_MSG(test, 0, err, "Decryption failed for %s", tv->name);
377 KUNIT_ASSERT_MEMEQ_MSG(test, tv->ptext, decrypted, tv->data_len,
378 "Wrong plaintext for %s", tv->name);
379}
380
381static void test_aes_gcm_test_vectors(struct kunit *test)
382{
383 for (size_t i = 0; i < ARRAY_SIZE(aes_gcm_testvecs); i++)
384 test_aes_gcm_one_test_vector(test, &aes_gcm_testvecs[i]);
385}
386
387static int aes_gcm_init_test(struct aes_gcm_ctx *ctx, u64 data_len, u64 ad_len,
388 const u8 *nonce, size_t nonce_len,
389 const struct aes_gcm_key *key)
390{
391 if (nonce_len != AES_GCM_NONCE_LEN)
392 return -EINVAL;
393 /*
394 * Ignore data_len and ad_len. Incremental AES-GCM doesn't need them at
395 * initialization time.
396 */
397 aes_gcm_init(ctx, nonce, key);
398 return 0;
399}
400
401static int aes_gcm_encrypt_test(u8 *dst, const u8 *src, size_t data_len,
402 u8 *authtag, const u8 *ad, size_t ad_len,
403 const u8 *nonce, size_t nonce_len,
404 const struct aes_gcm_key *key)
405{
406 if (nonce_len != AES_GCM_NONCE_LEN)
407 return -EINVAL;
408 /* aes_gcm_encrypt() returns void. */
409 aes_gcm_encrypt(dst, src, data_len, authtag, ad, ad_len, nonce, key);
410 return 0;
411}
412
413static int aes_gcm_decrypt_test(u8 *dst, const u8 *src, size_t data_len,
414 const u8 *authtag, const u8 *ad, size_t ad_len,
415 const u8 *nonce, size_t nonce_len,
416 const struct aes_gcm_key *key)
417{
418 if (nonce_len != AES_GCM_NONCE_LEN)
419 return -EINVAL;
420 return aes_gcm_decrypt(dst, src, data_len, authtag, ad, ad_len, nonce,
421 key);
422}
423
424static const size_t aes_gcm_valid_key_lens[] = { 16, 24, 32 };
425#define AEAD_MAX_KEY_LEN 32
426#define AEAD_VALID_KEY_LENS aes_gcm_valid_key_lens
427
428static const size_t aes_gcm_valid_nonce_lens[] = { AES_GCM_NONCE_LEN };
429#define AEAD_MAX_NONCE_LEN AES_GCM_NONCE_LEN
430#define AEAD_VALID_NONCE_LENS aes_gcm_valid_nonce_lens
431
432static const size_t aes_gcm_valid_tag_lens[] = { 4, 8, 12, 13, 14, 15, 16 };
433#define AEAD_MAX_TAG_LEN 16
434#define AEAD_VALID_TAG_LENS aes_gcm_valid_tag_lens
435
436#define AEAD_KEY aes_gcm_key
437#define AEAD_CTX aes_gcm_ctx
438#define AEAD_PREPAREKEY aes_gcm_preparekey
439#define AEAD_ENCRYPT aes_gcm_encrypt_test
440#define AEAD_DECRYPT aes_gcm_decrypt_test
441
442#define AEAD_INIT aes_gcm_init_test
443#define AEAD_AUTH_UPDATE aes_gcm_auth_update
444#define AEAD_ENCRYPT_UPDATE aes_gcm_encrypt_update
445#define AEAD_DECRYPT_UPDATE aes_gcm_decrypt_update
446#define AEAD_ENCRYPT_FINAL aes_gcm_encrypt_final
447#define AEAD_DECRYPT_FINAL aes_gcm_decrypt_final
448
449/* This value was generated by gen-aead-testvecs.py. */
450static const u8 aes_gcm_monte_carlo_checksum[BLAKE2S_HASH_SIZE] = {
451 0x6d, 0xd0, 0x6e, 0x6b, 0xde, 0x3e, 0x92, 0x9f, 0xae, 0x1f, 0xf1,
452 0x84, 0x99, 0x5a, 0x9e, 0x7b, 0xfe, 0x20, 0x9e, 0x22, 0x7c, 0x5f,
453 0x15, 0xb3, 0x59, 0x89, 0xd0, 0xb7, 0x74, 0x5d, 0xd2, 0xa5,
454};
455#define AEAD_MONTE_CARLO_CHECKSUM aes_gcm_monte_carlo_checksum
456
457#include "aead-test-template.h"
458
459static struct kunit_case aes_gcm_test_cases[] = {
460 KUNIT_CASE(test_aes_gcm_test_vectors),
461 AEAD_KUNIT_CASES,
462 {},
463};
464
465static struct kunit_suite aes_gcm_test_suite = {
466 .name = "aes_gcm",
467 .test_cases = aes_gcm_test_cases,
468};
469kunit_test_suite(aes_gcm_test_suite);
470
471MODULE_DESCRIPTION("KUnit tests and benchmark for AES-GCM");
472MODULE_LICENSE("GPL");
scripts/crypto/gen-aead-testvecs.py+11−2
@@ -41,6 +41,15 @@ def gen_monte_carlo_checksum(alg): · 40 unmodified lines
41 key, tag_length=tag_len41 key, tag_length=tag_len
42 )42 )
43 ct_and_tag = ccm.encrypt(nonce, pt, ad)43 ct_and_tag = ccm.encrypt(nonce, pt, ad)
44 elif alg == "aes-gcm":
45 key_len = [16, 24, 32][data_len % 3]
46 key = rand_bytes(key_len)
47 nonce = rand_bytes(12)
48 tag_len = [4, 8, 12, 13, 14, 15, 16][data_len % 7]
49 gcm = cryptography.hazmat.primitives.ciphers.aead.AESGCM(key)
50 # python-cryptography supports only 16-byte GCM tags. However, in
51 # GCM, shorter tags are simply truncated. Do that below.
52 ct_and_tag = gcm.encrypt(nonce, pt, ad)[: data_len + tag_len]
44 53
45 blake2s.update(ct_and_tag)54 blake2s.update(ct_and_tag)
46 55
@@ -53,8 +62,8 @@ def gen_monte_carlo_checksum(alg): · 6 unmodified lines
53 print("};")62 print("};")
54 63
55 64
56if len(sys.argv) != 2 or sys.argv[1] not in ("aes-ccm"):65if len(sys.argv) != 2 or sys.argv[1] not in ("aes-ccm", "aes-gcm"):
57 sys.stderr.write("Usage: gen-aead-testvecs.py [aes-ccm]\n")66 sys.stderr.write("Usage: gen-aead-testvecs.py [aes-ccm|aes-gcm]\n")
58 sys.exit(1)67 sys.exit(1)
59 68
60gen_monte_carlo_checksum(sys.argv[1])69gen_monte_carlo_checksum(sys.argv[1])