1138578Ssam/*- 2138578Ssam * Copyright (c) 2004 Sam Leffler, Errno Consulting 3138578Ssam * All rights reserved. 4138578Ssam * 5138578Ssam * Redistribution and use in source and binary forms, with or without 6138578Ssam * modification, are permitted provided that the following conditions 7138578Ssam * are met: 8138578Ssam * 1. Redistributions of source code must retain the above copyright 9138578Ssam * notice, this list of conditions and the following disclaimer. 10138578Ssam * 2. Redistributions in binary form must reproduce the above copyright 11138578Ssam * notice, this list of conditions and the following disclaimer in the 12138578Ssam * documentation and/or other materials provided with the distribution. 13138578Ssam * 3. The name of the author may not be used to endorse or promote products 14138578Ssam * derived from this software without specific prior written permission. 15138578Ssam * 16138578Ssam * Alternatively, this software may be distributed under the terms of the 17138578Ssam * GNU General Public License ("GPL") version 2 as published by the Free 18138578Ssam * Software Foundation. 19138578Ssam * 20138578Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21138578Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22138578Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23138578Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24138578Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25138578Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26138578Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27138578Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28138578Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29138578Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30138578Ssam * 31138578Ssam * $FreeBSD: releng/10.3/tools/regression/net80211/wep/test_wep.c 269738 2014-08-08 19:39:40Z delphij $ 32138578Ssam */ 33138578Ssam 34138578Ssam/* 35138578Ssam * WEP test module. 36138578Ssam * 37138578Ssam * Test vectors come from section I.7.2 of P802.11i/D7.0, October 2003. 38138578Ssam * 39138578Ssam * To use this tester load the net80211 layer (either as a module or 40138578Ssam * by statically configuring it into your kernel), then insmod this 41138578Ssam * module. It should automatically run all test cases and print 42138578Ssam * information for each. To run one or more tests you can specify a 43138578Ssam * tests parameter to the module that is a bit mask of the set of tests 44138578Ssam * you want; e.g. insmod wep_test tests=7 will run only test mpdu's 45138578Ssam * 1, 2, and 3. 46138578Ssam */ 47138578Ssam#include <sys/param.h> 48138578Ssam#include <sys/kernel.h> 49138578Ssam#include <sys/systm.h> 50138578Ssam#include <sys/mbuf.h> 51138578Ssam#include <sys/module.h> 52138578Ssam 53138578Ssam#include <sys/socket.h> 54138578Ssam 55138578Ssam#include <net/if.h> 56138578Ssam#include <net/if_media.h> 57138578Ssam 58138578Ssam#include <net80211/ieee80211_var.h> 59138578Ssam 60138578Ssam/* 61138578SsamMPDU data 62138578Ssam aa aa 03 00 00 00 08 00 45 00 00 4e 66 1a 00 00 80 11 be 64 0a 00 01 22 63138578Ssam 0a ff ff ff 00 89 00 89 00 3a 00 00 80 a6 01 10 00 01 00 00 00 00 00 00 64138578Ssam 20 45 43 45 4a 45 48 45 43 46 43 45 50 46 45 45 49 45 46 46 43 43 41 43 65138578Ssam 41 43 41 43 41 43 41 41 41 00 00 20 00 01 66138578Ssam 67138578SsamRC4 encryption is performed as follows: 68138578Ssam17 69138578Ssam18 Key fb 02 9e 30 31 32 33 34 70138578SsamPlaintext 71138578Ssam aa aa 03 00 00 00 08 00 45 00 00 4e 66 1a 00 00 80 11 be 64 0a 00 01 72138578Ssam 22 0a ff ff ff 00 89 00 89 00 3a 00 00 80 a6 01 10 00 01 00 00 00 00 73138578Ssam 00 00 20 45 43 45 4a 45 48 45 43 46 43 45 50 46 45 45 49 45 46 46 43 74138578Ssam 43 41 43 41 43 41 43 41 43 41 41 41 00 00 20 00 01 1b d0 b6 04 75138578SsamCiphertext 76138578Ssam f6 9c 58 06 bd 6c e8 46 26 bc be fb 94 74 65 0a ad 1f 79 09 b0 f6 4d 77138578Ssam 5f 58 a5 03 a2 58 b7 ed 22 eb 0e a6 49 30 d3 a0 56 a5 57 42 fc ce 14 78138578Ssam 1d 48 5f 8a a8 36 de a1 8d f4 2c 53 80 80 5a d0 c6 1a 5d 6f 58 f4 10 79138578Ssam 40 b2 4b 7d 1a 69 38 56 ed 0d 43 98 e7 ae e3 bf 0e 2a 2c a8 f7 80138578SsamThe plaintext consists of the MPDU data, followed by a 4-octet CRC-32 81138578Ssamcalculated over the MPDU data. 82138578Ssam19 The expanded MPDU, after WEP encapsulation, is as follows: 83138578Ssam20 84138578Ssam21 IV fb 02 9e 80 85138578SsamMPDU data 86138578Ssam 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 87138578Ssam 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 88138578Ssam 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 89138578Ssam 0d 43 98 e7 ae e3 bf 0e 90138578SsamICV 2a 2c a8 f7 91138578Ssam*/ 92138578Ssamstatic const u_int8_t test1_key[] = { /* TK (w/o IV) */ 93138578Ssam 0x30, 0x31, 0x32, 0x33, 0x34, 94138578Ssam}; 95138578Ssamstatic const u_int8_t test1_plaintext[] = { /* Plaintext MPDU */ 96138578Ssam 0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28, /* 802.11 Header */ 97138578Ssam 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 98138578Ssam 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33, 99138578Ssam 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, /* Plaintext data */ 100138578Ssam 0x45, 0x00, 0x00, 0x4e, 0x66, 0x1a, 0x00, 0x00, 101138578Ssam 0x80, 0x11, 0xbe, 0x64, 0x0a, 0x00, 0x01, 0x22, 102138578Ssam 0x0a, 0xff, 0xff, 0xff, 0x00, 0x89, 0x00, 0x89, 103138578Ssam 0x00, 0x3a, 0x00, 0x00, 0x80, 0xa6, 0x01, 0x10, 104138578Ssam 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 105138578Ssam 0x20, 0x45, 0x43, 0x45, 0x4a, 0x45, 0x48, 0x45, 106138578Ssam 0x43, 0x46, 0x43, 0x45, 0x50, 0x46, 0x45, 0x45, 107138578Ssam 0x49, 0x45, 0x46, 0x46, 0x43, 0x43, 0x41, 0x43, 108138578Ssam 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x41, 109138578Ssam 0x41, 0x00, 0x00, 0x20, 0x00, 0x01, 110138578Ssam}; 111138578Ssamstatic const u_int8_t test1_encrypted[] = { /* Encrypted MPDU */ 112138578Ssam 0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28, 113138578Ssam 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 114138578Ssam 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33, 115138578Ssam 0xfb, 0x02, 0x9e, 0x80, 0xf6, 0x9c, 0x58, 0x06, 116138578Ssam 0xbd, 0x6c, 0xe8, 0x46, 0x26, 0xbc, 0xbe, 0xfb, 117138578Ssam 0x94, 0x74, 0x65, 0x0a, 0xad, 0x1f, 0x79, 0x09, 118138578Ssam 0xb0, 0xf6, 0x4d, 0x5f, 0x58, 0xa5, 0x03, 0xa2, 119138578Ssam 0x58, 0xb7, 0xed, 0x22, 0xeb, 0x0e, 0xa6, 0x49, 120138578Ssam 0x30, 0xd3, 0xa0, 0x56, 0xa5, 0x57, 0x42, 0xfc, 121138578Ssam 0xce, 0x14, 0x1d, 0x48, 0x5f, 0x8a, 0xa8, 0x36, 122138578Ssam 0xde, 0xa1, 0x8d, 0xf4, 0x2c, 0x53, 0x80, 0x80, 123138578Ssam 0x5a, 0xd0, 0xc6, 0x1a, 0x5d, 0x6f, 0x58, 0xf4, 124138578Ssam 0x10, 0x40, 0xb2, 0x4b, 0x7d, 0x1a, 0x69, 0x38, 125138578Ssam 0x56, 0xed, 0x0d, 0x43, 0x98, 0xe7, 0xae, 0xe3, 126138578Ssam 0xbf, 0x0e, 0x2a, 0x2c, 0xa8, 0xf7, 127138578Ssam}; 128138578Ssam 129138578Ssam/* XXX fix byte order of iv */ 130138578Ssam#define TEST(n,name,cipher,keyix,iv0,iv1,iv2,iv3) { \ 131138578Ssam name, IEEE80211_CIPHER_##cipher,keyix, { iv2,iv1,iv0,iv3 }, \ 132138578Ssam test##n##_key, sizeof(test##n##_key), \ 133138578Ssam test##n##_plaintext, sizeof(test##n##_plaintext), \ 134138578Ssam test##n##_encrypted, sizeof(test##n##_encrypted) \ 135138578Ssam} 136138578Ssam 137138578Ssamstruct ciphertest { 138138578Ssam const char *name; 139138578Ssam int cipher; 140138578Ssam int keyix; 141138578Ssam u_int8_t iv[4]; 142138578Ssam const u_int8_t *key; 143138578Ssam size_t key_len; 144138578Ssam const u_int8_t *plaintext; 145138578Ssam size_t plaintext_len; 146138578Ssam const u_int8_t *encrypted; 147138578Ssam size_t encrypted_len; 148138578Ssam} weptests[] = { 149138578Ssam TEST(1, "WEP test mpdu 1", WEP, 2, 0xfb, 0x02, 0x9e, 0x80), 150138578Ssam}; 151138578Ssam 152138578Ssamstatic void 153138578Ssamdumpdata(const char *tag, const void *p, size_t len) 154138578Ssam{ 155138578Ssam int i; 156138578Ssam 157138578Ssam printf("%s: 0x%p len %u", tag, p, len); 158138578Ssam for (i = 0; i < len; i++) { 159138578Ssam if ((i % 16) == 0) 160138578Ssam printf("\n%03d:", i); 161138578Ssam printf(" %02x", ((const u_int8_t *)p)[i]); 162138578Ssam } 163138578Ssam printf("\n"); 164138578Ssam} 165138578Ssam 166138578Ssamstatic void 167138578Ssamcmpfail(const void *gen, size_t genlen, const void *ref, size_t reflen) 168138578Ssam{ 169138578Ssam int i; 170138578Ssam 171138578Ssam for (i = 0; i < genlen; i++) 172138578Ssam if (((const u_int8_t *)gen)[i] != ((const u_int8_t *)ref)[i]) { 173138578Ssam printf("first difference at byte %u\n", i); 174138578Ssam break; 175138578Ssam } 176138578Ssam dumpdata("Generated", gen, genlen); 177138578Ssam dumpdata("Reference", ref, reflen); 178138578Ssam} 179138578Ssam 180138578Ssamstruct wep_ctx_hw { /* for use with h/w support */ 181138578Ssam struct ieee80211com *wc_ic; /* for diagnostics */ 182138578Ssam u_int32_t wc_iv; /* initial vector for crypto */ 183138578Ssam}; 184138578Ssam 185138578Ssamstatic int 186138578Ssamruntest(struct ieee80211com *ic, struct ciphertest *t) 187138578Ssam{ 188138578Ssam struct ieee80211_key key; 189138578Ssam struct mbuf *m = NULL; 190138578Ssam const struct ieee80211_cipher *cip; 191138578Ssam u_int8_t mac[IEEE80211_ADDR_LEN]; 192138578Ssam struct wep_ctx_hw *ctx; 193138578Ssam 194138578Ssam printf("%s: ", t->name); 195138578Ssam 196138578Ssam /* 197138578Ssam * Setup key. 198138578Ssam */ 199138578Ssam memset(&key, 0, sizeof(key)); 200138578Ssam key.wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 201138578Ssam key.wk_cipher = &ieee80211_cipher_none; 202145904Savatar if (!ieee80211_crypto_newkey(ic, t->cipher, 203145904Savatar IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, &key)) { 204138578Ssam printf("FAIL: ieee80211_crypto_newkey failed\n"); 205138578Ssam goto bad; 206138578Ssam } 207138578Ssam 208138578Ssam memcpy(key.wk_key, t->key, t->key_len); 209138578Ssam key.wk_keylen = t->key_len; 210138578Ssam if (!ieee80211_crypto_setkey(ic, &key, mac)) { 211138578Ssam printf("FAIL: ieee80211_crypto_setkey failed\n"); 212138578Ssam goto bad; 213138578Ssam } 214138578Ssam cip = key.wk_cipher; 215138578Ssam 216138578Ssam /* 217138578Ssam * Craft frame from plaintext data. 218138578Ssam */ 219138578Ssam cip = key.wk_cipher; 220138578Ssam m = m_getcl(M_NOWAIT, MT_HEADER, M_PKTHDR); 221138578Ssam memcpy(mtod(m, void *), t->encrypted, t->encrypted_len); 222138578Ssam m->m_len = t->encrypted_len; 223138578Ssam m->m_pkthdr.len = m->m_len; 224138578Ssam 225138578Ssam /* 226138578Ssam * Decrypt frame. 227138578Ssam */ 228138578Ssam if (!cip->ic_decap(&key, m)) { 229138578Ssam printf("FAIL: wep decap failed\n"); 230138578Ssam cmpfail(mtod(m, const void *), m->m_pkthdr.len, 231138578Ssam t->plaintext, t->plaintext_len); 232138578Ssam goto bad; 233138578Ssam } 234138578Ssam /* 235138578Ssam * Verify: frame length, frame contents. 236138578Ssam */ 237138578Ssam if (m->m_pkthdr.len != t->plaintext_len) { 238138578Ssam printf("FAIL: decap botch; length mismatch\n"); 239138578Ssam cmpfail(mtod(m, const void *), m->m_pkthdr.len, 240138578Ssam t->plaintext, t->plaintext_len); 241138578Ssam goto bad; 242138578Ssam } else if (memcmp(mtod(m, const void *), t->plaintext, t->plaintext_len)) { 243138578Ssam printf("FAIL: decap botch; data does not compare\n"); 244138578Ssam cmpfail(mtod(m, const void *), m->m_pkthdr.len, 245269738Sdelphij t->plaintext, t->plaintext_len); 246138578Ssam goto bad; 247138578Ssam } 248138578Ssam 249138578Ssam /* 250138578Ssam * Encrypt frame. 251138578Ssam */ 252138578Ssam ctx = (struct wep_ctx_hw *) key.wk_private; 253138578Ssam memcpy(&ctx->wc_iv, t->iv, sizeof(t->iv)); /* for encap/encrypt */ 254138578Ssam if (!cip->ic_encap(&key, m, t->keyix<<6)) { 255138578Ssam printf("FAIL: wep encap failed\n"); 256138578Ssam goto bad; 257138578Ssam } 258138578Ssam /* 259138578Ssam * Verify: frame length, frame contents. 260138578Ssam */ 261138578Ssam if (m->m_pkthdr.len != t->encrypted_len) { 262138578Ssam printf("FAIL: encap data length mismatch\n"); 263138578Ssam cmpfail(mtod(m, const void *), m->m_pkthdr.len, 264138578Ssam t->encrypted, t->encrypted_len); 265138578Ssam goto bad; 266138578Ssam } else if (memcmp(mtod(m, const void *), t->encrypted, m->m_pkthdr.len)) { 267138578Ssam printf("FAIL: encrypt data does not compare\n"); 268138578Ssam cmpfail(mtod(m, const void *), m->m_pkthdr.len, 269138578Ssam t->encrypted, t->encrypted_len); 270138578Ssam dumpdata("Plaintext", t->plaintext, t->plaintext_len); 271138578Ssam goto bad; 272138578Ssam } 273138578Ssam m_freem(m); 274138578Ssam ieee80211_crypto_delkey(ic, &key); 275138578Ssam printf("PASS\n"); 276138578Ssam return 1; 277138578Ssambad: 278138578Ssam if (m != NULL) 279138578Ssam m_freem(m); 280138578Ssam ieee80211_crypto_delkey(ic, &key); 281138578Ssam return 0; 282138578Ssam} 283138578Ssam 284138578Ssam/* 285138578Ssam * Module glue. 286138578Ssam */ 287138578Ssam 288138578Ssamstatic int tests = -1; 289138578Ssamstatic int debug = 0; 290138578Ssam 291138578Ssamstatic int 292138578Ssaminit_crypto_wep_test(void) 293138578Ssam{ 294138578Ssam#define N(a) (sizeof(a)/sizeof(a[0])) 295138578Ssam struct ieee80211com ic; 296138578Ssam int i, pass, total; 297138578Ssam 298138578Ssam memset(&ic, 0, sizeof(ic)); 299138578Ssam if (debug) 300138578Ssam ic.ic_debug = IEEE80211_MSG_CRYPTO; 301138578Ssam ieee80211_crypto_attach(&ic); 302138578Ssam pass = 0; 303138578Ssam total = 0; 304138578Ssam for (i = 0; i < N(weptests); i++) 305138578Ssam if (tests & (1<<i)) { 306138578Ssam total++; 307138578Ssam pass += runtest(&ic, &weptests[i]); 308138578Ssam } 309138578Ssam printf("%u of %u 802.11i WEP test vectors passed\n", pass, total); 310138578Ssam ieee80211_crypto_detach(&ic); 311138578Ssam return (pass == total ? 0 : -1); 312138578Ssam#undef N 313138578Ssam} 314138578Ssam 315138578Ssamstatic int 316138578Ssamtest_wep_modevent(module_t mod, int type, void *unused) 317138578Ssam{ 318138578Ssam switch (type) { 319138578Ssam case MOD_LOAD: 320138578Ssam (void) init_crypto_wep_test(); 321138578Ssam return 0; 322138578Ssam case MOD_UNLOAD: 323138578Ssam return 0; 324138578Ssam } 325138578Ssam return EINVAL; 326138578Ssam} 327138578Ssam 328138578Ssamstatic moduledata_t test_wep_mod = { 329138578Ssam "test_wep", 330138578Ssam test_wep_modevent, 331241394Skevlo 0 332138578Ssam}; 333138578SsamDECLARE_MODULE(test_wep, test_wep_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 334138578SsamMODULE_VERSION(test_wep, 1); 335138578SsamMODULE_DEPEND(test_wep, wlan, 1, 1, 1); 336