1 /* test_cmac_mode.c - TinyCrypt AES-CMAC tests (including SP 800-38B tests) */
2
3 /*
4 * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * - Neither the name of Intel Corporation nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * DESCRIPTION
34 * This module tests the following AES-CMAC test (including SP 800-38B):
35 *
36 * Scenarios tested include:
37 * - CMAC test #1 (GF(2^128) double))
38 * - CMAC test #2 null msg (SP 800-38B test vector #1)
39 * - CMAC test #3 1 block msg (SP 800-38B test vector #2)
40 * - CMAC test #4 320 bit msg (SP 800-38B test vector #3)
41 * - CMAC test #5 512 bit msg (SP 800-38B test vector #4)
42 */
43
44 #include <tinycrypt/cmac_mode.h>
45 #include <tinycrypt/constants.h>
46 #include <tinycrypt/aes.h>
47 #include <test_utils.h>
48
49 #include <stdio.h>
50 #include <string.h>
51
52 #define BUF_LEN 16
53
show(const char * label,const uint8_t * s,size_t slen)54 static void show(const char *label, const uint8_t *s, size_t slen)
55 {
56 unsigned int i;
57
58 TC_PRINT("%s\t", label);
59 for (i = 0; i < slen; ++i) {
60 TC_PRINT("%02x", s[i]);
61 }
62 TC_PRINT("\n");
63 }
64
65 extern void gf_double(uint8_t *out, uint8_t *in);
66
verify_gf_2_128_double(uint8_t * K1,uint8_t * K2,struct tc_cmac_struct s)67 static int verify_gf_2_128_double(uint8_t *K1, uint8_t *K2,
68 struct tc_cmac_struct s)
69 {
70 int result = TC_PASS;
71
72 TC_PRINT("Performing CMAC test #1 (GF(2^128) double):\n");
73
74 uint8_t zero[BUF_LEN];
75 uint8_t L[BUF_LEN];
76 const uint8_t l[BUF_LEN] = {
77 0x7d, 0xf7, 0x6b, 0x0c, 0x1a, 0xb8, 0x99, 0xb3,
78 0x3e, 0x42, 0xf0, 0x47, 0xb9, 0x1b, 0x54, 0x6f
79 };
80 const uint8_t k1[BUF_LEN] = {
81 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
82 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
83 };
84 const uint8_t k2[BUF_LEN] = {
85 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
86 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
87 };
88
89 (void) memset(zero, '\0', sizeof(zero));
90 tc_aes_encrypt(L, zero, s.sched);
91 if (memcmp(L, l, BUF_LEN) != 0) {
92 TC_ERROR("%s: AES encryption failed\n", __func__);
93 show("expected L =", l, sizeof(l));
94 show("computed L =", L, sizeof(L));
95 return TC_FAIL;
96 }
97
98 gf_double(K1, L);
99 if (memcmp(K1, k1, BUF_LEN) != 0) {
100 TC_ERROR("%s: gf_2_128_double failed when msb = 0\n", __func__);
101 show("expected K1 =", k1, sizeof(k1));
102 show("computed K1 =", K1, sizeof(k1));
103 return TC_FAIL;
104 }
105
106 gf_double(K2, K1);
107 if (memcmp(K2, k2, BUF_LEN) != 0) {
108 TC_ERROR("%s: gf_2_128_double failed when msb = 1\n", __func__);
109 show("expected K2 =", k2, sizeof(k2));
110 show("computed K2 =", K2, sizeof(k2));
111 return TC_FAIL;
112 }
113
114 TC_END_RESULT(result);
115 return result;
116 }
117
verify_cmac_null_msg(TCCmacState_t s)118 static int verify_cmac_null_msg(TCCmacState_t s)
119 {
120 int result = TC_PASS;
121
122 TC_PRINT("Performing CMAC test #2 (SP 800-38B test vector #1):\n");
123
124 const uint8_t tag[BUF_LEN] = {
125 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
126 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
127 };
128 uint8_t Tag[BUF_LEN];
129
130 (void) tc_cmac_init(s);
131 (void) tc_cmac_update(s, (const uint8_t *) 0, 0);
132 (void) tc_cmac_final(Tag, s);
133
134 if (memcmp(Tag, tag, BUF_LEN) != 0) {
135 TC_ERROR("%s: aes_cmac failed with null msg = 1\n", __func__);
136 show("expected Tag =", tag, sizeof(tag));
137 show("computed Tag =", Tag, sizeof(Tag));
138 return TC_FAIL;
139 }
140
141 TC_END_RESULT(result);
142 return result;
143 }
144
verify_cmac_1_block_msg(TCCmacState_t s)145 static int verify_cmac_1_block_msg(TCCmacState_t s)
146 {
147 int result = TC_PASS;
148
149 TC_PRINT("Performing CMAC test #3 (SP 800-38B test vector #2):\n");
150
151 const uint8_t msg[BUF_LEN] = {
152 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
153 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
154 };
155 const uint8_t tag[BUF_LEN] = {
156 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
157 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
158 };
159 uint8_t Tag[BUF_LEN];
160
161 (void) tc_cmac_init(s);
162 (void) tc_cmac_update(s, msg, sizeof(msg));
163 (void) tc_cmac_final(Tag, s);
164
165 if (memcmp(Tag, tag, BUF_LEN) != 0) {
166 TC_ERROR("%s: aes_cmac failed with 1 block msg\n", __func__);
167 show("aes_cmac failed with 1 block msg =", msg, sizeof(msg));
168 show("expected Tag =", tag, sizeof(tag));
169 show("computed Tag =", Tag, sizeof(Tag));
170 return TC_FAIL;
171 }
172
173 TC_END_RESULT(result);
174 return result;
175 }
176
verify_cmac_320_bit_msg(TCCmacState_t s)177 static int verify_cmac_320_bit_msg(TCCmacState_t s)
178 {
179 int result = TC_PASS;
180
181 TC_PRINT("Performing CMAC test #4 (SP 800-38B test vector #3):\n");
182
183 const uint8_t msg[40] = {
184 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
185 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
186 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
187 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
188 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11
189 };
190 const uint8_t tag[BUF_LEN] = {
191 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
192 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
193 };
194 uint8_t Tag[BUF_LEN];
195
196 (void) tc_cmac_init(s);
197 (void) tc_cmac_update(s, msg, sizeof(msg));
198 (void) tc_cmac_final(Tag, s);
199
200 if (memcmp(Tag, tag, BUF_LEN) != 0) {
201 TC_ERROR("%s: aes_cmac failed with 320 bit msg\n", __func__);
202 show("aes_cmac failed with 320 bit msg =", msg, sizeof(msg));
203 show("expected Tag =", tag, sizeof(tag));
204 show("computed Tag =", Tag, sizeof(Tag));
205 return TC_FAIL;
206 }
207
208 TC_END_RESULT(result);
209 return result;
210 }
211
verify_cmac_512_bit_msg(TCCmacState_t s)212 static int verify_cmac_512_bit_msg(TCCmacState_t s)
213 {
214 int result = TC_PASS;
215
216 TC_PRINT("Performing CMAC test #5 (SP 800-38B test vector #4)\n");
217
218 const uint8_t msg[64] = {
219 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
220 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
221 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
222 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
223 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
224 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
225 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
226 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
227 };
228 const uint8_t tag[BUF_LEN] = {
229 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
230 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
231 };
232 uint8_t Tag[BUF_LEN];
233
234 (void)tc_cmac_init(s);
235 (void)tc_cmac_update(s, msg, sizeof(msg));
236 (void)tc_cmac_final(Tag, s);
237
238 if (memcmp(Tag, tag, BUF_LEN) != 0) {
239 TC_ERROR("%s: aes_cmac failed with 512 bit msg\n", __func__);
240 show("aes_cmac failed with 512 bit msg =", msg, sizeof(msg));
241 show("expected Tag =", tag, sizeof(tag));
242 show("computed Tag =", Tag, sizeof(Tag));
243 return TC_FAIL;
244 }
245
246 TC_END_RESULT(result);
247 return result;
248 }
249
250 /*
251 * Main task to test CMAC
252 * effects: returns 1 if all tests pass
253 * exceptions: returns a negative value if some test fails
254 */
main(void)255 int main(void)
256 {
257
258 int result = TC_PASS;
259
260 struct tc_cmac_struct state;
261 struct tc_aes_key_sched_struct sched;
262
263 const uint8_t key[BUF_LEN] = {
264 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
265 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
266 };
267 uint8_t K1[BUF_LEN], K2[BUF_LEN];
268
269 TC_START("Performing CMAC tests:");
270
271 (void) tc_cmac_setup(&state, key, &sched);
272 result = verify_gf_2_128_double(K1, K2, state);
273 if (result == TC_FAIL) {
274 /* terminate test */
275 TC_ERROR("CMAC test #1 (128 double) failed.\n");
276 goto exitTest;
277 }
278 (void) tc_cmac_setup(&state, key, &sched);
279 result = verify_cmac_null_msg(&state);
280 if (result == TC_FAIL) {
281 /* terminate test */
282 TC_ERROR("CMAC test #2 (null msg) failed.\n");
283 goto exitTest;
284 }
285 (void) tc_cmac_setup(&state, key, &sched);
286 result = verify_cmac_1_block_msg(&state);
287 if (result == TC_FAIL) {
288 /* terminate test */
289 TC_ERROR("CMAC test #3 (1 block msg)failed.\n");
290 goto exitTest;
291 }
292 (void) tc_cmac_setup(&state, key, &sched);
293 result = verify_cmac_320_bit_msg(&state);
294 if (result == TC_FAIL) {
295 /* terminate test */
296 TC_ERROR("CMAC test #4 (320 bit msg) failed.\n");
297 goto exitTest;
298 }
299 (void) tc_cmac_setup(&state, key, &sched);
300 result = verify_cmac_512_bit_msg(&state);
301 if (result == TC_FAIL) {
302 /* terminate test */
303 TC_ERROR("CMAC test #5 (512 bit msg)failed.\n");
304 goto exitTest;
305 }
306
307 TC_PRINT("All CMAC tests succeeded!\n");
308
309 exitTest:
310 TC_END_RESULT(result);
311 TC_END_REPORT(result);
312
313 return result;
314 }
315