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