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