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