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