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