test_wep.c revision 269738
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: stable/10/tools/regression/net80211/wep/test_wep.c 269738 2014-08-08 19:39:40Z delphij $
32 */
33
34/*
35 * WEP test module.
36 *
37 * Test vectors come from section I.7.2 of P802.11i/D7.0, October 2003.
38 *
39 * To use this tester load the net80211 layer (either as a module or
40 * by statically configuring it into your kernel), then insmod this
41 * module.  It should automatically run all test cases and print
42 * information for each.  To run one or more tests you can specify a
43 * tests parameter to the module that is a bit mask of the set of tests
44 * you want; e.g. insmod wep_test tests=7 will run only test mpdu's
45 * 1, 2, and 3.
46 */
47#include <sys/param.h>
48#include <sys/kernel.h>
49#include <sys/systm.h>
50#include <sys/mbuf.h>
51#include <sys/module.h>
52
53#include <sys/socket.h>
54
55#include <net/if.h>
56#include <net/if_media.h>
57
58#include <net80211/ieee80211_var.h>
59
60/*
61MPDU data
62 aa aa 03 00 00 00 08 00 45 00 00 4e 66 1a 00 00 80 11 be 64 0a 00 01 22
63 0a ff ff ff 00 89 00 89 00 3a 00 00 80 a6 01 10 00 01 00 00 00 00 00 00
64 20 45 43 45 4a 45 48 45 43 46 43 45 50 46 45 45 49 45 46 46 43 43 41 43
65 41 43 41 43 41 43 41 41 41 00 00 20 00 01
66
67RC4 encryption is performed as follows:
6817
6918  Key  fb 02 9e 30 31 32 33 34
70Plaintext
71 aa aa 03 00 00 00 08 00 45 00 00 4e 66 1a 00 00 80 11 be 64 0a 00 01
72 22 0a ff ff ff 00 89 00 89 00 3a 00 00 80 a6 01 10 00 01 00 00 00 00
73 00 00 20 45 43 45 4a 45 48 45 43 46 43 45 50 46 45 45 49 45 46 46 43
74 43 41 43 41 43 41 43 41 43 41 41 41 00 00 20 00 01 1b d0 b6 04
75Ciphertext
76 f6 9c 58 06 bd 6c e8 46 26 bc be fb 94 74 65 0a ad 1f 79 09 b0 f6 4d
77 5f 58 a5 03 a2 58 b7 ed 22 eb 0e a6 49 30 d3 a0 56 a5 57 42 fc ce 14
78 1d 48 5f 8a a8 36 de a1 8d f4 2c 53 80 80 5a d0 c6 1a 5d 6f 58 f4 10
79 40 b2 4b 7d 1a 69 38 56 ed 0d 43 98 e7 ae e3 bf 0e 2a 2c a8 f7
80The plaintext consists of the MPDU data, followed by a 4-octet CRC-32
81calculated over the MPDU data.
8219  The expanded MPDU, after WEP encapsulation, is as follows:
8320
8421  IV  fb 02 9e 80
85MPDU  data
86 f6 9c 58 06 bd 6c e8 46 26 bc be fb 94 74 65 0a ad 1f 79 09 b0 f6 4d 5f 58 a5
87 03 a2 58 b7 ed 22 eb 0e a6 49 30 d3 a0 56 a5 57 42 fc ce 14 1d 48 5f 8a a8 36
88 de a1 8d f4 2c 53 80 80 5a d0 c6 1a 5d 6f 58 f4 10 40 b2 4b 7d 1a 69 38 56 ed
89 0d 43 98 e7 ae e3 bf 0e
90ICV  2a 2c a8 f7
91*/
92static const u_int8_t test1_key[] = {		/* TK (w/o IV) */
93	0x30, 0x31, 0x32, 0x33, 0x34,
94};
95static const u_int8_t test1_plaintext[] = {	/* Plaintext MPDU */
96	0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28,	/* 802.11 Header */
97	0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08,
98	0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33,
99	0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00,	/* Plaintext data */
100	0x45, 0x00, 0x00, 0x4e, 0x66, 0x1a, 0x00, 0x00,
101	0x80, 0x11, 0xbe, 0x64, 0x0a, 0x00, 0x01, 0x22,
102	0x0a, 0xff, 0xff, 0xff, 0x00, 0x89, 0x00, 0x89,
103	0x00, 0x3a, 0x00, 0x00, 0x80, 0xa6, 0x01, 0x10,
104	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105	0x20, 0x45, 0x43, 0x45, 0x4a, 0x45, 0x48, 0x45,
106	0x43, 0x46, 0x43, 0x45, 0x50, 0x46, 0x45, 0x45,
107	0x49, 0x45, 0x46, 0x46, 0x43, 0x43, 0x41, 0x43,
108	0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x41,
109	0x41, 0x00, 0x00, 0x20, 0x00, 0x01,
110};
111static const u_int8_t test1_encrypted[] = {	/* Encrypted MPDU */
112	0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28,
113	0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08,
114	0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33,
115	0xfb, 0x02, 0x9e, 0x80, 0xf6, 0x9c, 0x58, 0x06,
116	0xbd, 0x6c, 0xe8, 0x46, 0x26, 0xbc, 0xbe, 0xfb,
117	0x94, 0x74, 0x65, 0x0a, 0xad, 0x1f, 0x79, 0x09,
118	0xb0, 0xf6, 0x4d, 0x5f, 0x58, 0xa5, 0x03, 0xa2,
119	0x58, 0xb7, 0xed, 0x22, 0xeb, 0x0e, 0xa6, 0x49,
120	0x30, 0xd3, 0xa0, 0x56, 0xa5, 0x57, 0x42, 0xfc,
121	0xce, 0x14, 0x1d, 0x48, 0x5f, 0x8a, 0xa8, 0x36,
122	0xde, 0xa1, 0x8d, 0xf4, 0x2c, 0x53, 0x80, 0x80,
123	0x5a, 0xd0, 0xc6, 0x1a, 0x5d, 0x6f, 0x58, 0xf4,
124	0x10, 0x40, 0xb2, 0x4b, 0x7d, 0x1a, 0x69, 0x38,
125	0x56, 0xed, 0x0d, 0x43, 0x98, 0xe7, 0xae, 0xe3,
126	0xbf, 0x0e, 0x2a, 0x2c, 0xa8, 0xf7,
127};
128
129/* XXX fix byte order of iv */
130#define	TEST(n,name,cipher,keyix,iv0,iv1,iv2,iv3) { \
131	name, IEEE80211_CIPHER_##cipher,keyix, { iv2,iv1,iv0,iv3 }, \
132	test##n##_key,   sizeof(test##n##_key), \
133	test##n##_plaintext, sizeof(test##n##_plaintext), \
134	test##n##_encrypted, sizeof(test##n##_encrypted) \
135}
136
137struct ciphertest {
138	const char	*name;
139	int		cipher;
140	int		keyix;
141	u_int8_t	iv[4];
142	const u_int8_t	*key;
143	size_t		key_len;
144	const u_int8_t	*plaintext;
145	size_t		plaintext_len;
146	const u_int8_t	*encrypted;
147	size_t		encrypted_len;
148} weptests[] = {
149	TEST(1, "WEP test mpdu 1", WEP, 2, 0xfb, 0x02, 0x9e, 0x80),
150};
151
152static void
153dumpdata(const char *tag, const void *p, size_t len)
154{
155	int i;
156
157	printf("%s: 0x%p len %u", tag, p, len);
158	for (i = 0; i < len; i++) {
159		if ((i % 16) == 0)
160			printf("\n%03d:", i);
161		printf(" %02x", ((const u_int8_t *)p)[i]);
162	}
163	printf("\n");
164}
165
166static void
167cmpfail(const void *gen, size_t genlen, const void *ref, size_t reflen)
168{
169	int i;
170
171	for (i = 0; i < genlen; i++)
172		if (((const u_int8_t *)gen)[i] != ((const u_int8_t *)ref)[i]) {
173			printf("first difference at byte %u\n", i);
174			break;
175		}
176	dumpdata("Generated", gen, genlen);
177	dumpdata("Reference", ref, reflen);
178}
179
180struct wep_ctx_hw {			/* for use with h/w support */
181	struct ieee80211com *wc_ic;	/* for diagnostics */
182	u_int32_t	wc_iv;		/* initial vector for crypto */
183};
184
185static int
186runtest(struct ieee80211com *ic, struct ciphertest *t)
187{
188	struct ieee80211_key key;
189	struct mbuf *m = NULL;
190	const struct ieee80211_cipher *cip;
191	u_int8_t mac[IEEE80211_ADDR_LEN];
192	struct wep_ctx_hw *ctx;
193
194	printf("%s: ", t->name);
195
196	/*
197	 * Setup key.
198	 */
199	memset(&key, 0, sizeof(key));
200	key.wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
201	key.wk_cipher = &ieee80211_cipher_none;
202	if (!ieee80211_crypto_newkey(ic, t->cipher,
203	    IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, &key)) {
204		printf("FAIL: ieee80211_crypto_newkey failed\n");
205		goto bad;
206	}
207
208	memcpy(key.wk_key, t->key, t->key_len);
209	key.wk_keylen = t->key_len;
210	if (!ieee80211_crypto_setkey(ic, &key, mac)) {
211		printf("FAIL: ieee80211_crypto_setkey failed\n");
212		goto bad;
213	}
214	cip = key.wk_cipher;
215
216	/*
217	 * Craft frame from plaintext data.
218	 */
219	cip = key.wk_cipher;
220	m = m_getcl(M_NOWAIT, MT_HEADER, M_PKTHDR);
221	memcpy(mtod(m, void *), t->encrypted, t->encrypted_len);
222	m->m_len = t->encrypted_len;
223	m->m_pkthdr.len = m->m_len;
224
225	/*
226	 * Decrypt frame.
227	 */
228	if (!cip->ic_decap(&key, m)) {
229		printf("FAIL: wep decap failed\n");
230		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
231			t->plaintext, t->plaintext_len);
232		goto bad;
233	}
234	/*
235	 * Verify: frame length, frame contents.
236	 */
237	if (m->m_pkthdr.len != t->plaintext_len) {
238		printf("FAIL: decap botch; length mismatch\n");
239		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
240			t->plaintext, t->plaintext_len);
241		goto bad;
242	} else if (memcmp(mtod(m, const void *), t->plaintext, t->plaintext_len)) {
243		printf("FAIL: decap botch; data does not compare\n");
244		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
245			t->plaintext, t->plaintext_len);
246		goto bad;
247	}
248
249	/*
250	 * Encrypt frame.
251	 */
252	ctx = (struct wep_ctx_hw *) key.wk_private;
253	memcpy(&ctx->wc_iv, t->iv, sizeof(t->iv));	/* for encap/encrypt */
254	if (!cip->ic_encap(&key, m, t->keyix<<6)) {
255		printf("FAIL: wep encap failed\n");
256		goto bad;
257	}
258	/*
259	 * Verify: frame length, frame contents.
260	 */
261	if (m->m_pkthdr.len != t->encrypted_len) {
262		printf("FAIL: encap data length mismatch\n");
263		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
264			t->encrypted, t->encrypted_len);
265		goto bad;
266	} else if (memcmp(mtod(m, const void *), t->encrypted, m->m_pkthdr.len)) {
267		printf("FAIL: encrypt data does not compare\n");
268		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
269			t->encrypted, t->encrypted_len);
270		dumpdata("Plaintext", t->plaintext, t->plaintext_len);
271		goto bad;
272	}
273	m_freem(m);
274	ieee80211_crypto_delkey(ic, &key);
275	printf("PASS\n");
276	return 1;
277bad:
278	if (m != NULL)
279		m_freem(m);
280	ieee80211_crypto_delkey(ic, &key);
281	return 0;
282}
283
284/*
285 * Module glue.
286 */
287
288static	int tests = -1;
289static	int debug = 0;
290
291static int
292init_crypto_wep_test(void)
293{
294#define	N(a)	(sizeof(a)/sizeof(a[0]))
295	struct ieee80211com ic;
296	int i, pass, total;
297
298	memset(&ic, 0, sizeof(ic));
299	if (debug)
300		ic.ic_debug = IEEE80211_MSG_CRYPTO;
301	ieee80211_crypto_attach(&ic);
302	pass = 0;
303	total = 0;
304	for (i = 0; i < N(weptests); i++)
305		if (tests & (1<<i)) {
306			total++;
307			pass += runtest(&ic, &weptests[i]);
308		}
309	printf("%u of %u 802.11i WEP test vectors passed\n", pass, total);
310	ieee80211_crypto_detach(&ic);
311	return (pass == total ? 0 : -1);
312#undef N
313}
314
315static int
316test_wep_modevent(module_t mod, int type, void *unused)
317{
318	switch (type) {
319	case MOD_LOAD:
320		(void) init_crypto_wep_test();
321		return 0;
322	case MOD_UNLOAD:
323		return 0;
324	}
325	return EINVAL;
326}
327
328static moduledata_t test_wep_mod = {
329	"test_wep",
330	test_wep_modevent,
331	0
332};
333DECLARE_MODULE(test_wep, test_wep_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
334MODULE_VERSION(test_wep, 1);
335MODULE_DEPEND(test_wep, wlan, 1, 1, 1);
336