1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 *
4 * LibTomCrypt is a library that provides various cryptographic
5 * algorithms in a highly modular and flexible manner.
6 *
7 * The library is free for all purposes without any express
8 * guarantee it works.
9 */
10
11 /**
12 @file gcm_test.c
13 GCM implementation, testing, by Tom St Denis
14 */
15 #include "tomcrypt_private.h"
16
17 #ifdef LTC_GCM_MODE
18
19 /**
20 Test the GCM code
21 @return CRYPT_OK on success
22 */
gcm_test(void)23 int gcm_test(void)
24 {
25 #ifndef LTC_TEST
26 return CRYPT_NOP;
27 #else
28 static const struct {
29 unsigned char K[32];
30 int keylen;
31 unsigned char P[128];
32 unsigned long ptlen;
33 unsigned char A[128];
34 unsigned long alen;
35 unsigned char IV[128];
36 unsigned long IVlen;
37 unsigned char C[128];
38 unsigned char T[16];
39 } tests[] = {
40
41 /* test case #1 */
42 {
43 /* key */
44 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
46 16,
47
48 /* plaintext */
49 { 0 },
50 0,
51
52 /* AAD data */
53 { 0 },
54 0,
55
56 /* IV */
57 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00 },
59 12,
60
61 /* ciphertext */
62 { 0 },
63
64 /* tag */
65 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
66 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }
67 },
68
69 /* test case #2 */
70 {
71 /* key */
72 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
74 16,
75
76 /* PT */
77 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
79 16,
80
81 /* ADATA */
82 { 0 },
83 0,
84
85 /* IV */
86 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00 },
88 12,
89
90 /* CT */
91 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
92 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
93
94 /* TAG */
95 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
96 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }
97 },
98
99 /* test case #3 */
100 {
101 /* key */
102 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
103 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, },
104 16,
105
106 /* PT */
107 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
108 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
109 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
110 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
111 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
112 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
113 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
114 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, },
115 64,
116
117 /* ADATA */
118 { 0 },
119 0,
120
121 /* IV */
122 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
123 0xde, 0xca, 0xf8, 0x88, },
124 12,
125
126 /* CT */
127 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
128 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
129 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
130 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
131 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
132 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
133 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
134 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85, },
135
136 /* TAG */
137 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
138 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4, }
139 },
140
141 /* test case #4 */
142 {
143 /* key */
144 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
145 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, },
146 16,
147
148 /* PT */
149 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
150 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
151 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
152 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
153 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
154 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
155 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
156 0xba, 0x63, 0x7b, 0x39, },
157 60,
158
159 /* ADATA */
160 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
161 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
162 0xab, 0xad, 0xda, 0xd2, },
163 20,
164
165 /* IV */
166 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
167 0xde, 0xca, 0xf8, 0x88, },
168 12,
169
170 /* CT */
171 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
172 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
173 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
174 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
175 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
176 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
177 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
178 0x3d, 0x58, 0xe0, 0x91, },
179
180 /* TAG */
181 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
182 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, }
183
184 },
185
186 /* test case #5 */
187 {
188 /* key */
189 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
190 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, },
191 16,
192
193 /* PT */
194 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
195 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
196 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
197 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
198 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
199 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
200 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
201 0xba, 0x63, 0x7b, 0x39, },
202 60,
203
204 /* ADATA */
205 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
206 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
207 0xab, 0xad, 0xda, 0xd2, },
208 20,
209
210 /* IV */
211 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, },
212 8,
213
214 /* CT */
215 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
216 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
217 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
218 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
219 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
220 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
221 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
222 0xc2, 0x3f, 0x45, 0x98, },
223
224 /* TAG */
225 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
226 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb, }
227 },
228
229 /* test case #6 */
230 {
231 /* key */
232 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
233 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, },
234 16,
235
236 /* PT */
237 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
238 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
239 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
240 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
241 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
242 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
243 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
244 0xba, 0x63, 0x7b, 0x39, },
245 60,
246
247 /* ADATA */
248 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
249 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
250 0xab, 0xad, 0xda, 0xd2, },
251 20,
252
253 /* IV */
254 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
255 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
256 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
257 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
258 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
259 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
260 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
261 0xa6, 0x37, 0xb3, 0x9b, },
262 60,
263
264 /* CT */
265 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
266 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
267 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
268 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
269 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
270 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
271 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
272 0x4c, 0x34, 0xae, 0xe5, },
273
274 /* TAG */
275 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
276 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50, }
277 },
278
279 /* test case #46 from BG (catches the LTC bug of v1.15) */
280 {
281 /* key */
282 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
284 16,
285
286 /* PT */
287 { 0xa2, 0xaa, 0xb3, 0xad, 0x8b, 0x17, 0xac, 0xdd,
288 0xa2, 0x88, 0x42, 0x6c, 0xd7, 0xc4, 0x29, 0xb7,
289 0xca, 0x86, 0xb7, 0xac, 0xa0, 0x58, 0x09, 0xc7,
290 0x0c, 0xe8, 0x2d, 0xb2, 0x57, 0x11, 0xcb, 0x53,
291 0x02, 0xeb, 0x27, 0x43, 0xb0, 0x36, 0xf3, 0xd7,
292 0x50, 0xd6, 0xcf, 0x0d, 0xc0, 0xac, 0xb9, 0x29,
293 0x50, 0xd5, 0x46, 0xdb, 0x30, 0x8f, 0x93, 0xb4,
294 0xff, 0x24, 0x4a, 0xfa, 0x9d, 0xc7, 0x2b, 0xcd,
295 0x75, 0x8d, 0x2c },
296 67,
297
298 /* ADATA */
299 { 0x68, 0x8e, 0x1a, 0xa9, 0x84, 0xde, 0x92, 0x6d,
300 0xc7, 0xb4, 0xc4, 0x7f, 0x44 },
301 13,
302
303 /* IV */
304 { 0xb7, 0x21, 0x38, 0xb5, 0xa0, 0x5f, 0xf5, 0x07,
305 0x0e, 0x8c, 0xd9, 0x41, 0x83, 0xf7, 0x61, 0xd8 },
306 16,
307
308 /* CT */
309 { 0xcb, 0xc8, 0xd2, 0xf1, 0x54, 0x81, 0xa4, 0xcc,
310 0x7d, 0xd1, 0xe1, 0x9a, 0xaa, 0x83, 0xde, 0x56,
311 0x78, 0x48, 0x3e, 0xc3, 0x59, 0xae, 0x7d, 0xec,
312 0x2a, 0xb8, 0xd5, 0x34, 0xe0, 0x90, 0x6f, 0x4b,
313 0x46, 0x63, 0xfa, 0xff, 0x58, 0xa8, 0xb2, 0xd7,
314 0x33, 0xb8, 0x45, 0xee, 0xf7, 0xc9, 0xb3, 0x31,
315 0xe9, 0xe1, 0x0e, 0xb2, 0x61, 0x2c, 0x99, 0x5f,
316 0xeb, 0x1a, 0xc1, 0x5a, 0x62, 0x86, 0xcc, 0xe8,
317 0xb2, 0x97, 0xa8 },
318
319 /* TAG */
320 { 0x8d, 0x2d, 0x2a, 0x93, 0x72, 0x62, 0x6f, 0x6b,
321 0xee, 0x85, 0x80, 0x27, 0x6a, 0x63, 0x66, 0xbf }
322 }
323
324 /* rest of test cases are the same except AES key size changes... ignored... */
325 };
326 int idx, err;
327 unsigned long x, y;
328 unsigned char out[2][128], T[2][16];
329 gcm_state gcm;
330
331 /* find aes */
332 idx = find_cipher("aes");
333 if (idx == -1) {
334 idx = find_cipher("rijndael");
335 if (idx == -1) {
336 return CRYPT_NOP;
337 }
338 }
339
340 /* Special test case for empty AAD + empty PT */
341 y = sizeof(T[0]);
342 if ((err = gcm_init(&gcm, idx, tests[0].K, tests[0].keylen)) != CRYPT_OK) return err;
343 if ((err = gcm_add_iv(&gcm, tests[0].IV, tests[0].IVlen)) != CRYPT_OK) return err;
344 /* intentionally skip gcm_add_aad + gcm_process */
345 if ((err = gcm_done(&gcm, T[0], &y)) != CRYPT_OK) return err;
346 if (compare_testvector(T[0], y, tests[0].T, 16, "GCM Encrypt Tag-special", 0)) return CRYPT_FAIL_TESTVECTOR;
347
348 for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
349 y = sizeof(T[0]);
350 if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen,
351 tests[x].IV, tests[x].IVlen,
352 tests[x].A, tests[x].alen,
353 (unsigned char*)tests[x].P, tests[x].ptlen,
354 out[0], T[0], &y, GCM_ENCRYPT)) != CRYPT_OK) {
355 return err;
356 }
357
358 if (compare_testvector(out[0], tests[x].ptlen, tests[x].C, tests[x].ptlen, "GCM CT", x)) {
359 return CRYPT_FAIL_TESTVECTOR;
360 }
361
362 if (compare_testvector(T[0], y, tests[x].T, 16, "GCM Encrypt Tag", x)) {
363 return CRYPT_FAIL_TESTVECTOR;
364 }
365
366 y = sizeof(T[1]);
367 XMEMCPY(T[1], tests[x].T, 16);
368 if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen,
369 tests[x].IV, tests[x].IVlen,
370 tests[x].A, tests[x].alen,
371 out[1], tests[x].ptlen,
372 out[0], T[1], &y, GCM_DECRYPT)) != CRYPT_OK) {
373 return err;
374 }
375
376 if (compare_testvector(out[1], tests[x].ptlen, tests[x].P, tests[x].ptlen, "GCM PT", x)) {
377 return CRYPT_FAIL_TESTVECTOR;
378 }
379 }
380
381 /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */
382 {
383 unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
384 unsigned char iv[] = { 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b };
385 unsigned char valid_tag[] = { 0xd8,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 };
386 unsigned char invalid_tag[] = { 0xd9,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 };
387 unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f };
388 unsigned char ct[] = { 0xeb,0x15,0x6d,0x08,0x1e,0xd6,0xb6,0xb5,0x5f,0x46,0x12,0xf0,0x21,0xd8,0x7b,0x39 };
389 unsigned char pt[20] = { 0 };
390 unsigned long taglen;
391
392 /* VALID tag */
393 taglen = sizeof(valid_tag);
394 err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0,
395 pt, sizeof(ct), ct, valid_tag, &taglen, GCM_DECRYPT);
396 if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) {
397 return CRYPT_FAIL_TESTVECTOR;
398 }
399
400 /* INVALID tag */
401 taglen = sizeof(invalid_tag);
402 err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0,
403 pt, sizeof(ct), ct, invalid_tag, &taglen, GCM_DECRYPT);
404 if (err == CRYPT_OK) {
405 return CRYPT_FAIL_TESTVECTOR; /* should fail */
406 }
407 }
408
409 return CRYPT_OK;
410 #endif
411 }
412
413 #endif
414
415
416 /* ref: $Format:%D$ */
417 /* git commit: $Format:%H$ */
418 /* commit time: $Format:%ai$ */
419