xref: /freebsd/tools/regression/net80211/tkip/test_tkip.c (revision 1f4bcc459a76b7aa664f3fd557684cd0ba6da352)
1 /*-
2  * Copyright (c) 2004 Sam Leffler, Errno Consulting
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * Alternatively, this software may be distributed under the terms of the
17  * GNU General Public License ("GPL") version 2 as published by the Free
18  * Software Foundation.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD$
32  */
33 
34 /*
35  * TKIP test module.
36  */
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
40 #include <sys/mbuf.h>
41 #include <sys/module.h>
42 
43 #include <sys/socket.h>
44 
45 #include <net/if.h>
46 #include <net/if_var.h>
47 #include <net/if_media.h>
48 
49 #include <net80211/ieee80211_var.h>
50 
51 /*
52 Key	12 34 56 78 90 12 34 56 78 90 12 34 56 78 90 12
53 	34 56 78 90 12 34 56 78 90 12 34 56 78 90 12 34
54 PN	0x000000000001
55 IV	00 20 01 20 00 00 00 00
56 Phase1	bb 58 07 1f 9e 93 b4 38 25 4b
57 Phase2	00 20 01 4c fe 67 be d2 7c 86 7b 1b f8 02 8b 1c
58 */
59 
60 static const u_int8_t test1_key[] = {
61 	0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12,
62 	0x34, 0x56, 0x78, 0x90, 0x12,
63 
64 	0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78,		/* TX MIC */
65 	/*
66 	 * NB: 11i test vector specifies a RX MIC key different
67 	 *     from the TX key.  But this doesn't work to enmic,
68 	 *     encrypt, then decrypt, demic.  So instead we use
69 	 *     the same key for doing the MIC in each direction.
70 	 *
71 	 * XXX need additional vectors to test alternate MIC keys
72 	 */
73 #if 0
74 	0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34,		/* 11i RX MIC */
75 #else
76 	0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78,		/* TX copy */
77 #endif
78 };
79 static const u_int8_t test1_phase1[] = {
80 	0xbb, 0x58, 0x07, 0x1f, 0x9e, 0x93, 0xb4, 0x38, 0x25, 0x4b
81 };
82 static const u_int8_t test1_phase2[] = {
83 	0x00, 0x20, 0x01, 0x4c, 0xfe, 0x67, 0xbe, 0xd2, 0x7c, 0x86,
84 	0x7b, 0x1b, 0xf8, 0x02, 0x8b, 0x1c,
85 };
86 
87 /* Plaintext MPDU with MIC */
88 static const u_int8_t test1_plaintext[] = {
89 0x08,0x42,0x2c,0x00,0x02,0x03,0x04,0x05,0x06,0x08,0x02,0x03,0x04,0x05,0x06,0x07,
90 0x02,0x03,0x04,0x05,0x06,0x07,0xd0,0x02,
91 0xaa,0xaa,0x03,0x00,0x00,0x00,0x08,0x00,0x45,0x00,0x00,0x54,0x00,0x00,0x40,0x00,
92 0x40,0x01,0xa5,0x55,0xc0,0xa8,0x0a,0x02,0xc0,0xa8,0x0a,0x01,0x08,0x00,0x3a,0xb0,
93 0x00,0x00,0x00,0x00,0xcd,0x4c,0x05,0x00,0x00,0x00,0x00,0x00,0x08,0x09,0x0a,0x0b,
94 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,
95 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,
96 0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
97 /* MIC */ 0x68,0x81,0xa3,0xf3,0xd6,0x48,0xd0,0x3c
98 };
99 
100 /* Encrypted MPDU with MIC and ICV */
101 static const u_int8_t test1_encrypted[] = {
102 0x08,0x42,0x2c,0x00,0x02,0x03,0x04,0x05,0x06,0x08,0x02,0x03,0x04,0x05,0x06,0x07,
103 0x02,0x03,0x04,0x05,0x06,0x07,0xd0,0x02,0x00,0x20,0x01,0x20,0x00,0x00,0x00,0x00,
104 0xc0,0x0e,0x14,0xfc,0xe7,0xcf,0xab,0xc7,0x75,0x47,0xe6,0x66,0xe5,0x7c,0x0d,0xac,
105 0x70,0x4a,0x1e,0x35,0x8a,0x88,0xc1,0x1c,0x8e,0x2e,0x28,0x2e,0x38,0x01,0x02,0x7a,
106 0x46,0x56,0x05,0x5e,0xe9,0x3e,0x9c,0x25,0x47,0x02,0xe9,0x73,0x58,0x05,0xdd,0xb5,
107 0x76,0x9b,0xa7,0x3f,0x1e,0xbb,0x56,0xe8,0x44,0xef,0x91,0x22,0x85,0xd3,0xdd,0x6e,
108 0x54,0x1e,0x82,0x38,0x73,0x55,0x8a,0xdb,0xa0,0x79,0x06,0x8a,0xbd,0x7f,0x7f,0x50,
109 0x95,0x96,0x75,0xac,0xc4,0xb4,0xde,0x9a,0xa9,0x9c,0x05,0xf2,0x89,0xa7,0xc5,0x2f,
110 0xee,0x5b,0xfc,0x14,0xf6,0xf8,0xe5,0xf8
111 };
112 
113 #define	TEST(n,name,cipher,keyix,pn) { \
114 	name, IEEE80211_CIPHER_##cipher,keyix, pn##LL, \
115 	test##n##_key,   sizeof(test##n##_key), \
116 	test##n##_phase1,   sizeof(test##n##_phase1), \
117 	test##n##_phase2,   sizeof(test##n##_phase2), \
118 	test##n##_plaintext, sizeof(test##n##_plaintext), \
119 	test##n##_encrypted, sizeof(test##n##_encrypted) \
120 }
121 
122 struct ciphertest {
123 	const char	*name;
124 	int		cipher;
125 	int		keyix;
126 	u_int64_t	pn;
127 	const u_int8_t	*key;
128 	size_t		key_len;
129 	const u_int8_t	*phase1;
130 	size_t		phase1_len;
131 	const u_int8_t	*phase2;
132 	size_t		phase2_len;
133 	const u_int8_t	*plaintext;
134 	size_t		plaintext_len;
135 	const u_int8_t	*encrypted;
136 	size_t		encrypted_len;
137 } tkiptests[] = {
138 	TEST(1, "TKIP test mpdu 1", TKIP, 0, 0),
139 };
140 
141 struct tkip_ctx {
142 	struct ieee80211com *tc_ic;	/* for diagnostics */
143 
144 	uint16_t tx_ttak[5];
145 	uint8_t	tx_rc4key[16];
146 
147 	uint16_t rx_ttak[5];
148 	int	rx_phase1_done;
149 	uint8_t	rx_rc4key[16];
150 	uint64_t rx_rsc;		/* held until MIC verified */
151 };
152 
153 static void
154 dumpdata(const char *tag, const void *p, size_t len)
155 {
156 	int i;
157 
158 	printf("%s: 0x%p len %u", tag, p, len);
159 	for (i = 0; i < len; i++) {
160 		if ((i % 16) == 0)
161 			printf("\n%03d:", i);
162 		printf(" %02x", ((const u_int8_t *)p)[i]);
163 	}
164 	printf("\n");
165 }
166 
167 static void
168 cmpfail(const void *gen, size_t genlen, const void *ref, size_t reflen)
169 {
170 	int i;
171 
172 	for (i = 0; i < genlen; i++)
173 		if (((const u_int8_t *)gen)[i] != ((const u_int8_t *)ref)[i]) {
174 			printf("first difference at byte %u\n", i);
175 			break;
176 		}
177 	dumpdata("Generated", gen, genlen);
178 	dumpdata("Reference", ref, reflen);
179 }
180 
181 static int
182 runtest(struct ieee80211vap *vap, struct ciphertest *t)
183 {
184 	struct tkip_ctx *ctx;
185 	struct ieee80211_key *key = &vap->iv_nw_keys[t->keyix];
186 	struct mbuf *m = NULL;
187 	const struct ieee80211_cipher *cip;
188 	u_int len;
189 	int hdrlen;
190 
191 	printf("%s: ", t->name);
192 
193 	/*
194 	 * Setup key.
195 	 */
196 	memset(key, 0, sizeof(*key));
197 	key->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
198 	key->wk_cipher = &ieee80211_cipher_none;
199 	if (!ieee80211_crypto_newkey(vap, t->cipher,
200 	    IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, key)) {
201 		printf("FAIL: ieee80211_crypto_newkey failed\n");
202 		goto bad;
203 	}
204 
205 	memcpy(key->wk_key, t->key, t->key_len);
206 	key->wk_keylen = 128/NBBY;
207 	memset(key->wk_keyrsc, 0, sizeof(key->wk_keyrsc));
208 	key->wk_keytsc = t->pn;
209 	if (!ieee80211_crypto_setkey(vap, key)) {
210 		printf("FAIL: ieee80211_crypto_setkey failed\n");
211 		goto bad;
212 	}
213 
214 	/*
215 	 * Craft frame from plaintext data.
216 	 */
217 	cip = key->wk_cipher;
218 	m = m_getcl(M_NOWAIT, MT_HEADER, M_PKTHDR);
219 	m->m_data += cip->ic_header;
220 	len = t->plaintext_len - IEEE80211_WEP_MICLEN;
221 	memcpy(mtod(m, void *), t->plaintext, len);
222 	m->m_len = len;
223 	m->m_pkthdr.len = m->m_len;
224 	hdrlen = ieee80211_anyhdrsize(mtod(m, void *));
225 
226 	/*
227 	 * Add MIC.
228 	 */
229 	if (!ieee80211_crypto_enmic(vap, key, m, 1)) {
230 		printf("FAIL: tkip enmic failed\n");
231 		goto bad;
232 	}
233 	/*
234 	 * Verify: frame length, frame contents.
235 	 */
236 	if (m->m_pkthdr.len != t->plaintext_len) {
237 		printf("FAIL: enmic botch; length mismatch\n");
238 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
239 			t->plaintext, t->plaintext_len);
240 		goto bad;
241 	}
242 	if (memcmp(mtod(m, const void *), t->plaintext, t->plaintext_len)) {
243 		printf("FAIL: enmic botch\n");
244 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
245 			t->plaintext, t->plaintext_len);
246 		goto bad;
247 	}
248 	/*
249 	 * Encrypt frame w/ MIC.
250 	 */
251 	if (!cip->ic_encap(key, m)) {
252 		printf("FAIL: tkip encap failed\n");
253 		goto bad;
254 	}
255 	/*
256 	 * Verify: phase1, phase2, frame length, frame contents.
257 	 */
258 	ctx = key->wk_private;
259 	if (memcmp(ctx->tx_ttak, t->phase1, t->phase1_len)) {
260 		printf("FAIL: encrypt phase1 botch\n");
261 		cmpfail(ctx->tx_ttak, sizeof(ctx->tx_ttak),
262 			t->phase1, t->phase1_len);
263 		goto bad;
264 	} else if (memcmp(ctx->tx_rc4key, t->phase2, t->phase2_len)) {
265 		printf("FAIL: encrypt phase2 botch\n");
266 		cmpfail(ctx->tx_rc4key, sizeof(ctx->tx_rc4key),
267 			t->phase2, t->phase2_len);
268 		goto bad;
269 	} else if (m->m_pkthdr.len != t->encrypted_len) {
270 		printf("FAIL: encrypt data length mismatch\n");
271 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
272 			t->encrypted, t->encrypted_len);
273 		goto bad;
274 	} else if (memcmp(mtod(m, const void *), t->encrypted, m->m_pkthdr.len)) {
275 		printf("FAIL: encrypt data does not compare\n");
276 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
277 			t->encrypted, t->encrypted_len);
278 		dumpdata("Plaintext", t->plaintext, t->plaintext_len);
279 		goto bad;
280 	}
281 
282 	/*
283 	 * Decrypt frame.
284 	 */
285 	if (!cip->ic_decap(key, m, hdrlen)) {
286 		printf("tkip decap failed\n");
287 		/*
288 		 * Check reason for failure: phase1, phase2, frame data (ICV).
289 		 */
290 		if (memcmp(ctx->rx_ttak, t->phase1, t->phase1_len)) {
291 			printf("FAIL: decrypt phase1 botch\n");
292 			cmpfail(ctx->rx_ttak, sizeof(ctx->rx_ttak),
293 				t->phase1, t->phase1_len);
294 		} else if (memcmp(ctx->rx_rc4key, t->phase2, t->phase2_len)) {
295 			printf("FAIL: decrypt phase2 botch\n");
296 			cmpfail(ctx->rx_rc4key, sizeof(ctx->rx_rc4key),
297 				t->phase2, t->phase2_len);
298 		} else {
299 			printf("FAIL: decrypt data does not compare\n");
300 			cmpfail(mtod(m, const void *), m->m_pkthdr.len,
301 				t->plaintext, t->plaintext_len);
302 		}
303 		goto bad;
304 	}
305 	/*
306 	 * Verify: frame length, frame contents.
307 	 */
308 	if (m->m_pkthdr.len != t->plaintext_len) {
309 		printf("FAIL: decap botch; length mismatch\n");
310 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
311 			t->plaintext, t->plaintext_len);
312 		goto bad;
313 	}
314 	if (memcmp(mtod(m, const void *), t->plaintext, t->plaintext_len)) {
315 		printf("FAIL: decap botch; data does not compare\n");
316 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
317 			t->plaintext, t->plaintext_len);
318 		goto bad;
319 	}
320 	/*
321 	 * De-MIC decrypted frame.
322 	 */
323 	if (!ieee80211_crypto_demic(vap, key, m, 1)) {
324 		printf("FAIL: tkip demic failed\n");
325 		goto bad;
326 	}
327 	/* XXX check frame length and contents... */
328 	m_freem(m);
329 	ieee80211_crypto_delkey(vap, key);
330 	printf("PASS\n");
331 	return 1;
332 bad:
333 	if (m != NULL)
334 		m_freem(m);
335 	ieee80211_crypto_delkey(vap, key);
336 	return 0;
337 }
338 
339 /*
340  * Module glue.
341  */
342 
343 static	int debug = 0;
344 static	int tests = -1;
345 
346 static int
347 init_crypto_tkip_test(void)
348 {
349 	struct ieee80211com ic;
350 	struct ieee80211vap vap;
351 	struct ifnet ifp;
352 	int i, pass, total;
353 
354 	memset(&ic, 0, sizeof(ic));
355 	memset(&vap, 0, sizeof(vap));
356 	memset(&ifp, 0, sizeof(ifp));
357 
358 	ieee80211_crypto_attach(&ic);
359 
360 	/* some minimal initialization */
361 	strncpy(ifp.if_xname, "test_ccmp", sizeof(ifp.if_xname));
362 	vap.iv_ic = &ic;
363 	vap.iv_ifp = &ifp;
364 	if (debug)
365 		vap.iv_debug = IEEE80211_MSG_CRYPTO;
366 	ieee80211_crypto_vattach(&vap);
367 
368 	pass = 0;
369 	total = 0;
370 	for (i = 0; i < nitems(tkiptests); i++)
371 		if (tests & (1<<i)) {
372 			total++;
373 			pass += runtest(&vap, &tkiptests[i]);
374 		}
375 	printf("%u of %u 802.11i TKIP test vectors passed\n", pass, total);
376 
377 	ieee80211_crypto_vdetach(&vap);
378 	ieee80211_crypto_detach(&ic);
379 
380 	return (pass == total ? 0 : -1);
381 }
382 
383 static int
384 test_tkip_modevent(module_t mod, int type, void *unused)
385 {
386 	switch (type) {
387 	case MOD_LOAD:
388 		(void) init_crypto_tkip_test();
389 		return 0;
390 	case MOD_UNLOAD:
391 		return 0;
392 	}
393 	return EINVAL;
394 }
395 
396 static moduledata_t test_tkip_mod = {
397 	"test_tkip",
398 	test_tkip_modevent,
399 	0
400 };
401 DECLARE_MODULE(test_tkip, test_tkip_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
402 MODULE_VERSION(test_tkip, 1);
403 MODULE_DEPEND(test_tkip, wlan, 1, 1, 1);
404