xref: /openssl/test/cmactest.c (revision 2c536c8b)
1 /*
2  * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 /*
11  * CMAC low level APIs are deprecated for public use, but still ok for internal
12  * use.
13  */
14 #include "internal/deprecated.h"
15 
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 
20 #include "internal/nelem.h"
21 
22 #include <openssl/cmac.h>
23 #include <openssl/aes.h>
24 #include <openssl/evp.h>
25 
26 #include "testutil.h"
27 
28 static const char xtskey[32] = {
29     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
30     0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
31     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
32 };
33 
34 static struct test_st {
35     const char key[32];
36     int key_len;
37     unsigned char data[4096];
38     int data_len;
39     const char *mac;
40 } test[] = {
41     {
42         {
43             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
44             0x0b, 0x0c, 0x0d, 0x0e, 0x0f
45         },
46         16,
47         "My test data",
48         12,
49         "29cec977c48f63c200bd5c4a6881b224"
50     },
51     {
52         {
53             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
54             0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
55             0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
56         },
57         32,
58         "My test data",
59         12,
60         "db6493aa04e4761f473b2b453c031c9a"
61     },
62     {
63         {
64             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
65             0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
66             0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
67         },
68         32,
69         "My test data again",
70         18,
71         "65c11c75ecf590badd0a5e56cbb8af60"
72     },
73     /* for aes-128-cbc */
74     {
75         {
76             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
77             0x0b, 0x0c, 0x0d, 0x0e, 0x0f
78         },
79         16,
80         /* repeat the string below until filling 3072 bytes */
81         "#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#",
82         3072,
83         "35da8a02a7afce90e5b711308cee2dee"
84     },
85     /* for aes-192-cbc */
86     {
87         {
88             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
89             0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
90             0x16, 0x17
91         },
92         24,
93         /* repeat the string below until filling 4095 bytes */
94         "#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#",
95         4095,
96         "59053f4e81f3593610f987adb547c5b2"
97     },
98     /* for aes-256-cbc */
99     {
100         {
101             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
102             0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
103             0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
104         },
105         32,
106         /* repeat the string below until filling 2560 bytes */
107         "#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#",
108         2560,
109         "9c6cf85f7f4baca99725764a0df973a9"
110     },
111     /* for des-ede3-cbc */
112     {
113         {
114             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
115             0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
116             0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
117         },
118         24,
119         /* repeat the string below until filling 2048 bytes */
120         "#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#",
121         2048,
122         "2c2fccc7fcc5d98a"
123     },
124     /* for sm4-cbc */
125     {
126         {
127             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
128             0x0b, 0x0c, 0x0d, 0x0e, 0x0f
129         },
130         16,
131         /* repeat the string below until filling 2049 bytes */
132         "#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#",
133         2049,
134         "c9a9cbc82a3b2d96074e386fce1216f2"
135     },
136 };
137 
138 static char *pt(unsigned char *md, unsigned int len);
139 
test_cmac_bad(void)140 static int test_cmac_bad(void)
141 {
142     CMAC_CTX *ctx = NULL;
143     int ret = 0;
144 
145     ctx = CMAC_CTX_new();
146     if (!TEST_ptr(ctx)
147         || !TEST_false(CMAC_Init(ctx, NULL, 0, NULL, NULL))
148         || !TEST_false(CMAC_Update(ctx, test[0].data, test[0].data_len))
149            /* Should be able to pass cipher first, and then key */
150         || !TEST_true(CMAC_Init(ctx, NULL, 0, EVP_aes_128_cbc(), NULL))
151            /* Must have a key */
152         || !TEST_false(CMAC_Update(ctx, test[0].data, test[0].data_len))
153            /* Now supply the key */
154         || !TEST_true(CMAC_Init(ctx, test[0].key, test[0].key_len, NULL, NULL))
155            /* Update should now work */
156         || !TEST_true(CMAC_Update(ctx, test[0].data, test[0].data_len))
157            /* XTS is not a suitable cipher to use */
158         || !TEST_false(CMAC_Init(ctx, xtskey, sizeof(xtskey), EVP_aes_128_xts(),
159                                  NULL))
160         || !TEST_false(CMAC_Update(ctx, test[0].data, test[0].data_len)))
161         goto err;
162 
163     ret = 1;
164 err:
165     CMAC_CTX_free(ctx);
166     return ret;
167 }
168 
test_cmac_run(void)169 static int test_cmac_run(void)
170 {
171     char *p;
172     CMAC_CTX *ctx = NULL;
173     unsigned char buf[AES_BLOCK_SIZE];
174     size_t len;
175     int ret = 0;
176     size_t case_idx = 0;
177 
178     ctx = CMAC_CTX_new();
179 
180     /* Construct input data, fill repeatedly until reaching data length */
181     for (case_idx = 0; case_idx < OSSL_NELEM(test); case_idx++) {
182         size_t str_len = strlen((char *)test[case_idx].data);
183         size_t fill_len = test[case_idx].data_len - str_len;
184         size_t fill_idx = str_len;
185         while (fill_len > 0) {
186             if (fill_len > str_len) {
187                 memcpy(&test[case_idx].data[fill_idx], test[case_idx].data, str_len);
188                 fill_len -= str_len;
189                 fill_idx += str_len;
190             } else {
191                 memcpy(&test[case_idx].data[fill_idx], test[case_idx].data, fill_len);
192                 fill_len = 0;
193             }
194         }
195     }
196 
197     if (!TEST_true(CMAC_Init(ctx, test[0].key, test[0].key_len,
198                              EVP_aes_128_cbc(), NULL))
199         || !TEST_true(CMAC_Update(ctx, test[0].data, test[0].data_len))
200         || !TEST_true(CMAC_Final(ctx, buf, &len)))
201         goto err;
202 
203     p = pt(buf, len);
204     if (!TEST_str_eq(p, test[0].mac))
205         goto err;
206 
207     if (!TEST_true(CMAC_Init(ctx, test[1].key, test[1].key_len,
208                              EVP_aes_256_cbc(), NULL))
209         || !TEST_true(CMAC_Update(ctx, test[1].data, test[1].data_len))
210         || !TEST_true(CMAC_Final(ctx, buf, &len)))
211         goto err;
212 
213     p = pt(buf, len);
214     if (!TEST_str_eq(p, test[1].mac))
215         goto err;
216 
217     if (!TEST_true(CMAC_Init(ctx, test[2].key, test[2].key_len, NULL, NULL))
218         || !TEST_true(CMAC_Update(ctx, test[2].data, test[2].data_len))
219         || !TEST_true(CMAC_Final(ctx, buf, &len)))
220         goto err;
221     p = pt(buf, len);
222     if (!TEST_str_eq(p, test[2].mac))
223         goto err;
224     /* Test reusing a key */
225     if (!TEST_true(CMAC_Init(ctx, NULL, 0, NULL, NULL))
226         || !TEST_true(CMAC_Update(ctx, test[2].data, test[2].data_len))
227         || !TEST_true(CMAC_Final(ctx, buf, &len)))
228         goto err;
229     p = pt(buf, len);
230     if (!TEST_str_eq(p, test[2].mac))
231         goto err;
232 
233     /* Test setting the cipher and key separately */
234     if (!TEST_true(CMAC_Init(ctx, NULL, 0, EVP_aes_256_cbc(), NULL))
235         || !TEST_true(CMAC_Init(ctx, test[2].key, test[2].key_len, NULL, NULL))
236         || !TEST_true(CMAC_Update(ctx, test[2].data, test[2].data_len))
237         || !TEST_true(CMAC_Final(ctx, buf, &len)))
238         goto err;
239     p = pt(buf, len);
240     if (!TEST_str_eq(p, test[2].mac))
241         goto err;
242 
243     /* Test data length is greater than 1 block length */
244     if (!TEST_true(CMAC_Init(ctx, test[3].key, test[3].key_len,
245                              EVP_aes_128_cbc(), NULL))
246         || !TEST_true(CMAC_Update(ctx, test[3].data, test[3].data_len))
247         || !TEST_true(CMAC_Final(ctx, buf, &len)))
248         goto err;
249     p = pt(buf, len);
250     if (!TEST_str_eq(p, test[3].mac))
251         goto err;
252 
253     if (!TEST_true(CMAC_Init(ctx, test[4].key, test[4].key_len,
254                              EVP_aes_192_cbc(), NULL))
255         || !TEST_true(CMAC_Update(ctx, test[4].data, test[4].data_len))
256         || !TEST_true(CMAC_Final(ctx, buf, &len)))
257         goto err;
258     p = pt(buf, len);
259     if (!TEST_str_eq(p, test[4].mac))
260         goto err;
261 
262     if (!TEST_true(CMAC_Init(ctx, test[5].key, test[5].key_len,
263                              EVP_aes_256_cbc(), NULL))
264         || !TEST_true(CMAC_Update(ctx, test[5].data, test[5].data_len))
265         || !TEST_true(CMAC_Final(ctx, buf, &len)))
266         goto err;
267     p = pt(buf, len);
268     if (!TEST_str_eq(p, test[5].mac))
269         goto err;
270 
271 #ifndef OPENSSL_NO_DES
272     if (!TEST_true(CMAC_Init(ctx, test[6].key, test[6].key_len,
273                              EVP_des_ede3_cbc(), NULL))
274         || !TEST_true(CMAC_Update(ctx, test[6].data, test[6].data_len))
275         || !TEST_true(CMAC_Final(ctx, buf, &len)))
276         goto err;
277     p = pt(buf, len);
278     if (!TEST_str_eq(p, test[6].mac))
279         goto err;
280 #endif
281 
282 #ifndef OPENSSL_NO_SM4
283     if (!TEST_true(CMAC_Init(ctx, test[7].key, test[7].key_len,
284                              EVP_sm4_cbc(), NULL))
285         || !TEST_true(CMAC_Update(ctx, test[7].data, test[7].data_len))
286         || !TEST_true(CMAC_Final(ctx, buf, &len)))
287         goto err;
288     p = pt(buf, len);
289     if (!TEST_str_eq(p, test[7].mac))
290         goto err;
291 #endif
292 
293     ret = 1;
294 err:
295     CMAC_CTX_free(ctx);
296     return ret;
297 }
298 
test_cmac_copy(void)299 static int test_cmac_copy(void)
300 {
301     char *p;
302     CMAC_CTX *ctx = NULL, *ctx2 = NULL;
303     unsigned char buf[AES_BLOCK_SIZE];
304     size_t len;
305     int ret = 0;
306 
307     ctx = CMAC_CTX_new();
308     ctx2 = CMAC_CTX_new();
309     if (!TEST_ptr(ctx) || !TEST_ptr(ctx2))
310         goto err;
311 
312     if (!TEST_true(CMAC_Init(ctx, test[0].key, test[0].key_len,
313                              EVP_aes_128_cbc(), NULL))
314         || !TEST_true(CMAC_Update(ctx, test[0].data, test[0].data_len))
315         || !TEST_true(CMAC_CTX_copy(ctx2, ctx))
316         || !TEST_true(CMAC_Final(ctx2, buf, &len)))
317         goto err;
318 
319     p = pt(buf, len);
320     if (!TEST_str_eq(p, test[0].mac))
321         goto err;
322 
323     ret = 1;
324 err:
325     CMAC_CTX_free(ctx2);
326     CMAC_CTX_free(ctx);
327     return ret;
328 }
329 
330 #define OSSL_HEX_CHARS_PER_BYTE 2
pt(unsigned char * md,unsigned int len)331 static char *pt(unsigned char *md, unsigned int len)
332 {
333     unsigned int i;
334     static char buf[81];
335 
336     for (i = 0; i < len && (i + 1) * OSSL_HEX_CHARS_PER_BYTE < sizeof(buf); i++)
337         BIO_snprintf(buf + i * OSSL_HEX_CHARS_PER_BYTE,
338                      OSSL_HEX_CHARS_PER_BYTE + 1, "%02x", md[i]);
339     return buf;
340 }
341 
setup_tests(void)342 int setup_tests(void)
343 {
344     ADD_TEST(test_cmac_bad);
345     ADD_TEST(test_cmac_run);
346     ADD_TEST(test_cmac_copy);
347     return 1;
348 }
349 
350