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/*
52Key	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
54PN	0x000000000001
55IV	00 20 01 20 00 00 00 00
56Phase1	bb 58 07 1f 9e 93 b4 38 25 4b
57Phase2	00 20 01 4c fe 67 be d2 7c 86 7b 1b f8 02 8b 1c
58*/
59
60static 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};
79static const u_int8_t test1_phase1[] = {
80	0xbb, 0x58, 0x07, 0x1f, 0x9e, 0x93, 0xb4, 0x38, 0x25, 0x4b
81};
82static 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 */
88static const u_int8_t test1_plaintext[] = {
890x08,0x42,0x2c,0x00,0x02,0x03,0x04,0x05,0x06,0x08,0x02,0x03,0x04,0x05,0x06,0x07,
900x02,0x03,0x04,0x05,0x06,0x07,0xd0,0x02,
910xaa,0xaa,0x03,0x00,0x00,0x00,0x08,0x00,0x45,0x00,0x00,0x54,0x00,0x00,0x40,0x00,
920x40,0x01,0xa5,0x55,0xc0,0xa8,0x0a,0x02,0xc0,0xa8,0x0a,0x01,0x08,0x00,0x3a,0xb0,
930x00,0x00,0x00,0x00,0xcd,0x4c,0x05,0x00,0x00,0x00,0x00,0x00,0x08,0x09,0x0a,0x0b,
940x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,
950x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,
960x2c,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 */
101static const u_int8_t test1_encrypted[] = {
1020x08,0x42,0x2c,0x00,0x02,0x03,0x04,0x05,0x06,0x08,0x02,0x03,0x04,0x05,0x06,0x07,
1030x02,0x03,0x04,0x05,0x06,0x07,0xd0,0x02,0x00,0x20,0x01,0x20,0x00,0x00,0x00,0x00,
1040xc0,0x0e,0x14,0xfc,0xe7,0xcf,0xab,0xc7,0x75,0x47,0xe6,0x66,0xe5,0x7c,0x0d,0xac,
1050x70,0x4a,0x1e,0x35,0x8a,0x88,0xc1,0x1c,0x8e,0x2e,0x28,0x2e,0x38,0x01,0x02,0x7a,
1060x46,0x56,0x05,0x5e,0xe9,0x3e,0x9c,0x25,0x47,0x02,0xe9,0x73,0x58,0x05,0xdd,0xb5,
1070x76,0x9b,0xa7,0x3f,0x1e,0xbb,0x56,0xe8,0x44,0xef,0x91,0x22,0x85,0xd3,0xdd,0x6e,
1080x54,0x1e,0x82,0x38,0x73,0x55,0x8a,0xdb,0xa0,0x79,0x06,0x8a,0xbd,0x7f,0x7f,0x50,
1090x95,0x96,0x75,0xac,0xc4,0xb4,0xde,0x9a,0xa9,0x9c,0x05,0xf2,0x89,0xa7,0xc5,0x2f,
1100xee,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
122struct 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
141struct 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
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 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;
332bad:
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
343static	int debug = 0;
344static	int tests = -1;
345
346static int
347init_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
383static int
384test_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
396static moduledata_t test_tkip_mod = {
397	"test_tkip",
398	test_tkip_modevent,
399	0
400};
401DECLARE_MODULE(test_tkip, test_tkip_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
402MODULE_VERSION(test_tkip, 1);
403MODULE_DEPEND(test_tkip, wlan, 1, 1, 1);
404