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