test_tkip.c revision 138578
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: head/tools/regression/net80211/tkip/test_tkip.c 138578 2004-12-08 17:45:53Z sam $
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_media.h>
47
48#include <net80211/ieee80211_var.h>
49
50/*
51Key	12 34 56 78 90 12 34 56 78 90 12 34 56 78 90 12
52	34 56 78 90 12 34 56 78 90 12 34 56 78 90 12 34
53PN	0x000000000001
54IV	00 20 01 20 00 00 00 00
55Phase1	bb 58 07 1f 9e 93 b4 38 25 4b
56Phase2	00 20 01 4c fe 67 be d2 7c 86 7b 1b f8 02 8b 1c
57*/
58
59static const u_int8_t test1_key[] = {
60	0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12,
61	0x34, 0x56, 0x78, 0x90, 0x12,
62
63	0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78,		/* TX MIC */
64	/*
65	 * NB: 11i test vector specifies a RX MIC key different
66	 *     from the TX key.  But this doesn't work to enmic,
67	 *     encrypt, then decrypt, demic.  So instead we use
68	 *     the same key for doing the MIC in each direction.
69	 *
70	 * XXX need additional vectors to test alternate MIC keys
71	 */
72#if 0
73	0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34,		/* 11i RX MIC */
74#else
75	0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78,		/* TX copy */
76#endif
77};
78static const u_int8_t test1_phase1[] = {
79	0xbb, 0x58, 0x07, 0x1f, 0x9e, 0x93, 0xb4, 0x38, 0x25, 0x4b
80};
81static const u_int8_t test1_phase2[] = {
82	0x00, 0x20, 0x01, 0x4c, 0xfe, 0x67, 0xbe, 0xd2, 0x7c, 0x86,
83	0x7b, 0x1b, 0xf8, 0x02, 0x8b, 0x1c,
84};
85
86/* Plaintext MPDU with MIC */
87static const u_int8_t test1_plaintext[] = {
880x08,0x42,0x2c,0x00,0x02,0x03,0x04,0x05,0x06,0x08,0x02,0x03,0x04,0x05,0x06,0x07,
890x02,0x03,0x04,0x05,0x06,0x07,0xd0,0x02,
900xaa,0xaa,0x03,0x00,0x00,0x00,0x08,0x00,0x45,0x00,0x00,0x54,0x00,0x00,0x40,0x00,
910x40,0x01,0xa5,0x55,0xc0,0xa8,0x0a,0x02,0xc0,0xa8,0x0a,0x01,0x08,0x00,0x3a,0xb0,
920x00,0x00,0x00,0x00,0xcd,0x4c,0x05,0x00,0x00,0x00,0x00,0x00,0x08,0x09,0x0a,0x0b,
930x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,
940x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,
950x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
96/* MIC */ 0x68,0x81,0xa3,0xf3,0xd6,0x48,0xd0,0x3c
97};
98
99/* Encrypted MPDU with MIC and ICV */
100static const u_int8_t test1_encrypted[] = {
1010x08,0x42,0x2c,0x00,0x02,0x03,0x04,0x05,0x06,0x08,0x02,0x03,0x04,0x05,0x06,0x07,
1020x02,0x03,0x04,0x05,0x06,0x07,0xd0,0x02,0x00,0x20,0x01,0x20,0x00,0x00,0x00,0x00,
1030xc0,0x0e,0x14,0xfc,0xe7,0xcf,0xab,0xc7,0x75,0x47,0xe6,0x66,0xe5,0x7c,0x0d,0xac,
1040x70,0x4a,0x1e,0x35,0x8a,0x88,0xc1,0x1c,0x8e,0x2e,0x28,0x2e,0x38,0x01,0x02,0x7a,
1050x46,0x56,0x05,0x5e,0xe9,0x3e,0x9c,0x25,0x47,0x02,0xe9,0x73,0x58,0x05,0xdd,0xb5,
1060x76,0x9b,0xa7,0x3f,0x1e,0xbb,0x56,0xe8,0x44,0xef,0x91,0x22,0x85,0xd3,0xdd,0x6e,
1070x54,0x1e,0x82,0x38,0x73,0x55,0x8a,0xdb,0xa0,0x79,0x06,0x8a,0xbd,0x7f,0x7f,0x50,
1080x95,0x96,0x75,0xac,0xc4,0xb4,0xde,0x9a,0xa9,0x9c,0x05,0xf2,0x89,0xa7,0xc5,0x2f,
1090xee,0x5b,0xfc,0x14,0xf6,0xf8,0xe5,0xf8
110};
111
112#define	TEST(n,name,cipher,keyix,pn) { \
113	name, IEEE80211_CIPHER_##cipher,keyix, pn##LL, \
114	test##n##_key,   sizeof(test##n##_key), \
115	test##n##_phase1,   sizeof(test##n##_phase1), \
116	test##n##_phase2,   sizeof(test##n##_phase2), \
117	test##n##_plaintext, sizeof(test##n##_plaintext), \
118	test##n##_encrypted, sizeof(test##n##_encrypted) \
119}
120
121struct ciphertest {
122	const char	*name;
123	int		cipher;
124	int		keyix;
125	u_int64_t	pn;
126	const u_int8_t	*key;
127	size_t		key_len;
128	const u_int8_t	*phase1;
129	size_t		phase1_len;
130	const u_int8_t	*phase2;
131	size_t		phase2_len;
132	const u_int8_t	*plaintext;
133	size_t		plaintext_len;
134	const u_int8_t	*encrypted;
135	size_t		encrypted_len;
136} tkiptests[] = {
137	TEST(1, "TKIP test mpdu 1", TKIP, 0, 0),
138};
139
140struct tkip_ctx {
141	struct ieee80211com *tc_ic;	/* for diagnostics */
142
143	uint16_t tx_ttak[5];
144	int	tx_phase1_done;
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
153static void
154dumpdata(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
167static void
168cmpfail(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
181static int
182runtest(struct ieee80211com *ic, struct ciphertest *t)
183{
184	struct tkip_ctx *ctx;
185	struct ieee80211_key key;
186	struct mbuf *m = NULL;
187	const struct ieee80211_cipher *cip;
188	u_int8_t mac[IEEE80211_ADDR_LEN];
189	u_int len;
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(ic, IEEE80211_CIPHER_TKIP, &key)) {
200		printf("FAIL: ieee80211_crypto_newkey failed\n");
201		goto bad;
202	}
203
204	memcpy(key.wk_key, t->key, t->key_len);
205	key.wk_keylen = 128/NBBY;
206	key.wk_keyrsc = 0;
207	key.wk_keytsc = t->pn;
208	if (!ieee80211_crypto_setkey(ic, &key, mac)) {
209		printf("FAIL: ieee80211_crypto_setkey failed\n");
210		goto bad;
211	}
212
213	/*
214	 * Craft frame from plaintext data.
215	 */
216	cip = key.wk_cipher;
217	m = m_getcl(M_NOWAIT, MT_HEADER, M_PKTHDR);
218	m->m_data += cip->ic_header;
219	len = t->plaintext_len - IEEE80211_WEP_MICLEN;
220	memcpy(mtod(m, void *), t->plaintext, len);
221	m->m_len = len;
222	m->m_pkthdr.len = m->m_len;
223
224	/*
225	 * Add MIC.
226	 */
227	if (!ieee80211_crypto_enmic(ic, &key, m)) {
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, t->keyix<<6)) {
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)) {
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(ic, &key, m)) {
322		printf("FAIL: tkip demic failed\n");
323		goto bad;
324	}
325	/* XXX check frame length and contents... */
326	printf("PASS\n");
327	return 1;
328bad:
329	if (m != NULL)
330		m_freem(m);
331	ieee80211_crypto_delkey(ic, &key);
332	return 0;
333}
334
335/*
336 * Module glue.
337 */
338
339static	int debug = 0;
340static	int tests = -1;
341
342static int
343init_crypto_tkip_test(void)
344{
345#define	N(a)	(sizeof(a)/sizeof(a[0]))
346	struct ieee80211com ic;
347	int i, pass, total;
348
349	memset(&ic, 0, sizeof(ic));
350	if (debug)
351		ic.ic_debug = IEEE80211_MSG_CRYPTO;
352	ieee80211_crypto_attach(&ic);
353
354	pass = 0;
355	total = 0;
356	for (i = 0; i < N(tkiptests); i++)
357		if (tests & (1<<i)) {
358			total++;
359			pass += runtest(&ic, &tkiptests[i]);
360		}
361	printf("%u of %u 802.11i TKIP test vectors passed\n", pass, total);
362	ieee80211_crypto_detach(&ic);
363	return (pass == total ? 0 : -1);
364#undef N
365}
366
367static int
368test_tkip_modevent(module_t mod, int type, void *unused)
369{
370	switch (type) {
371	case MOD_LOAD:
372		(void) init_crypto_tkip_test();
373		return 0;
374	case MOD_UNLOAD:
375		return 0;
376	}
377	return EINVAL;
378}
379
380static moduledata_t test_tkip_mod = {
381	"test_tkip",
382	test_tkip_modevent,
383	0
384};
385DECLARE_MODULE(test_tkip, test_tkip_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
386MODULE_VERSION(test_tkip, 1);
387MODULE_DEPEND(test_tkip, wlan, 1, 1, 1);
388