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