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_media.h> 57 58 #include <net80211/ieee80211_var.h> 59 60 /* 61 MPDU 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 67 RC4 encryption is performed as follows: 68 17 69 18 Key fb 02 9e 30 31 32 33 34 70 Plaintext 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 75 Ciphertext 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 80 The plaintext consists of the MPDU data, followed by a 4-octet CRC-32 81 calculated over the MPDU data. 82 19 The expanded MPDU, after WEP encapsulation, is as follows: 83 20 84 21 IV fb 02 9e 80 85 MPDU 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 90 ICV 2a 2c a8 f7 91 */ 92 static const u_int8_t test1_key[] = { /* TK (w/o IV) */ 93 0x30, 0x31, 0x32, 0x33, 0x34, 94 }; 95 static 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 }; 111 static 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 137 struct 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 152 static void 153 dumpdata(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 166 static void 167 cmpfail(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 180 struct 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 185 static int 186 runtest(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, sizeof(t->plaintext)); 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; 277 bad: 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 288 static int tests = -1; 289 static int debug = 0; 290 291 static int 292 init_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 315 static int 316 test_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 328 static moduledata_t test_wep_mod = { 329 "test_wep", 330 test_wep_modevent, 331 0 332 }; 333 DECLARE_MODULE(test_wep, test_wep_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 334 MODULE_VERSION(test_wep, 1); 335 MODULE_DEPEND(test_wep, wlan, 1, 1, 1); 336