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