aboutsummaryrefslogtreecommitdiff
path: root/tools/regression/net80211/wep/test_wep.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/regression/net80211/wep/test_wep.c')
-rw-r--r--tools/regression/net80211/wep/test_wep.c350
1 files changed, 350 insertions, 0 deletions
diff --git a/tools/regression/net80211/wep/test_wep.c b/tools/regression/net80211/wep/test_wep.c
new file mode 100644
index 000000000000..27ec33174e39
--- /dev/null
+++ b/tools/regression/net80211/wep/test_wep.c
@@ -0,0 +1,350 @@
+/*-
+ * Copyright (c) 2004 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * WEP test module.
+ *
+ * Test vectors come from section I.7.2 of P802.11i/D7.0, October 2003.
+ *
+ * To use this tester load the net80211 layer (either as a module or
+ * by statically configuring it into your kernel), then insmod this
+ * module. It should automatically run all test cases and print
+ * information for each. To run one or more tests you can specify a
+ * tests parameter to the module that is a bit mask of the set of tests
+ * you want; e.g. insmod wep_test tests=7 will run only test mpdu's
+ * 1, 2, and 3.
+ */
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_media.h>
+
+#include <net80211/ieee80211_var.h>
+
+/*
+MPDU data
+ aa aa 03 00 00 00 08 00 45 00 00 4e 66 1a 00 00 80 11 be 64 0a 00 01 22
+ 0a ff ff ff 00 89 00 89 00 3a 00 00 80 a6 01 10 00 01 00 00 00 00 00 00
+ 20 45 43 45 4a 45 48 45 43 46 43 45 50 46 45 45 49 45 46 46 43 43 41 43
+ 41 43 41 43 41 43 41 41 41 00 00 20 00 01
+
+RC4 encryption is performed as follows:
+17
+18 Key fb 02 9e 30 31 32 33 34
+Plaintext
+ aa aa 03 00 00 00 08 00 45 00 00 4e 66 1a 00 00 80 11 be 64 0a 00 01
+ 22 0a ff ff ff 00 89 00 89 00 3a 00 00 80 a6 01 10 00 01 00 00 00 00
+ 00 00 20 45 43 45 4a 45 48 45 43 46 43 45 50 46 45 45 49 45 46 46 43
+ 43 41 43 41 43 41 43 41 43 41 41 41 00 00 20 00 01 1b d0 b6 04
+Ciphertext
+ 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 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 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 0d 43 98 e7 ae e3 bf 0e 2a 2c a8 f7
+The plaintext consists of the MPDU data, followed by a 4-octet CRC-32
+calculated over the MPDU data.
+19 The expanded MPDU, after WEP encapsulation, is as follows:
+20
+21 IV fb 02 9e 80
+MPDU data
+ 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
+ 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
+ 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
+ 0d 43 98 e7 ae e3 bf 0e
+ICV 2a 2c a8 f7
+*/
+static const u_int8_t test1_key[] = { /* TK (w/o IV) */
+ 0x30, 0x31, 0x32, 0x33, 0x34,
+};
+static const u_int8_t test1_plaintext[] = { /* Plaintext MPDU */
+ 0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28, /* 802.11 Header */
+ 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08,
+ 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33,
+ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, /* Plaintext data */
+ 0x45, 0x00, 0x00, 0x4e, 0x66, 0x1a, 0x00, 0x00,
+ 0x80, 0x11, 0xbe, 0x64, 0x0a, 0x00, 0x01, 0x22,
+ 0x0a, 0xff, 0xff, 0xff, 0x00, 0x89, 0x00, 0x89,
+ 0x00, 0x3a, 0x00, 0x00, 0x80, 0xa6, 0x01, 0x10,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x45, 0x43, 0x45, 0x4a, 0x45, 0x48, 0x45,
+ 0x43, 0x46, 0x43, 0x45, 0x50, 0x46, 0x45, 0x45,
+ 0x49, 0x45, 0x46, 0x46, 0x43, 0x43, 0x41, 0x43,
+ 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x41,
+ 0x41, 0x00, 0x00, 0x20, 0x00, 0x01,
+};
+static const u_int8_t test1_encrypted[] = { /* Encrypted MPDU */
+ 0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28,
+ 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08,
+ 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33,
+ 0xfb, 0x02, 0x9e, 0x80, 0xf6, 0x9c, 0x58, 0x06,
+ 0xbd, 0x6c, 0xe8, 0x46, 0x26, 0xbc, 0xbe, 0xfb,
+ 0x94, 0x74, 0x65, 0x0a, 0xad, 0x1f, 0x79, 0x09,
+ 0xb0, 0xf6, 0x4d, 0x5f, 0x58, 0xa5, 0x03, 0xa2,
+ 0x58, 0xb7, 0xed, 0x22, 0xeb, 0x0e, 0xa6, 0x49,
+ 0x30, 0xd3, 0xa0, 0x56, 0xa5, 0x57, 0x42, 0xfc,
+ 0xce, 0x14, 0x1d, 0x48, 0x5f, 0x8a, 0xa8, 0x36,
+ 0xde, 0xa1, 0x8d, 0xf4, 0x2c, 0x53, 0x80, 0x80,
+ 0x5a, 0xd0, 0xc6, 0x1a, 0x5d, 0x6f, 0x58, 0xf4,
+ 0x10, 0x40, 0xb2, 0x4b, 0x7d, 0x1a, 0x69, 0x38,
+ 0x56, 0xed, 0x0d, 0x43, 0x98, 0xe7, 0xae, 0xe3,
+ 0xbf, 0x0e, 0x2a, 0x2c, 0xa8, 0xf7,
+};
+
+/* XXX fix byte order of iv */
+#define TEST(n,name,cipher,keyix,iv0,iv1,iv2,iv3) { \
+ name, IEEE80211_CIPHER_##cipher,keyix, { iv2,iv1,iv0,iv3 }, \
+ test##n##_key, sizeof(test##n##_key), \
+ test##n##_plaintext, sizeof(test##n##_plaintext), \
+ test##n##_encrypted, sizeof(test##n##_encrypted) \
+}
+
+struct ciphertest {
+ const char *name;
+ int cipher;
+ int keyix;
+ u_int8_t iv[4];
+ const u_int8_t *key;
+ size_t key_len;
+ const u_int8_t *plaintext;
+ size_t plaintext_len;
+ const u_int8_t *encrypted;
+ size_t encrypted_len;
+} weptests[] = {
+ TEST(1, "WEP test mpdu 1", WEP, 2, 0xfb, 0x02, 0x9e, 0x80),
+};
+
+static void
+dumpdata(const char *tag, const void *p, size_t len)
+{
+ int i;
+
+ printf("%s: 0x%p len %u", tag, p, len);
+ for (i = 0; i < len; i++) {
+ if ((i % 16) == 0)
+ printf("\n%03d:", i);
+ printf(" %02x", ((const u_int8_t *)p)[i]);
+ }
+ printf("\n");
+}
+
+static void
+cmpfail(const void *gen, size_t genlen, const void *ref, size_t reflen)
+{
+ int i;
+
+ for (i = 0; i < genlen; i++)
+ if (((const u_int8_t *)gen)[i] != ((const u_int8_t *)ref)[i]) {
+ printf("first difference at byte %u\n", i);
+ break;
+ }
+ dumpdata("Generated", gen, genlen);
+ dumpdata("Reference", ref, reflen);
+}
+
+struct wep_ctx_hw { /* for use with h/w support */
+ struct ieee80211vap *wc_vap; /* for diagnostics+statistics */
+ struct ieee80211com *wc_ic;
+ uint32_t wc_iv; /* initial vector for crypto */
+};
+
+static int
+runtest(struct ieee80211vap *vap, struct ciphertest *t)
+{
+ struct ieee80211_key *key = &vap->iv_nw_keys[t->keyix];
+ struct mbuf *m = NULL;
+ const struct ieee80211_cipher *cip;
+ struct wep_ctx_hw *ctx;
+ int hdrlen;
+
+ printf("%s: ", t->name);
+
+ /*
+ * Setup key.
+ */
+ memset(key, 0, sizeof(*key));
+ key->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
+ key->wk_cipher = &ieee80211_cipher_none;
+ if (!ieee80211_crypto_newkey(vap, t->cipher,
+ IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, key)) {
+ printf("FAIL: ieee80211_crypto_newkey failed\n");
+ goto bad;
+ }
+
+ memcpy(key->wk_key, t->key, t->key_len);
+ key->wk_keylen = t->key_len;
+ if (!ieee80211_crypto_setkey(vap, key)) {
+ printf("FAIL: ieee80211_crypto_setkey failed\n");
+ goto bad;
+ }
+
+ /*
+ * Craft frame from plaintext data.
+ */
+ cip = key->wk_cipher;
+ m = m_getcl(M_NOWAIT, MT_HEADER, M_PKTHDR);
+ memcpy(mtod(m, void *), t->encrypted, t->encrypted_len);
+ m->m_len = t->encrypted_len;
+ m->m_pkthdr.len = m->m_len;
+ hdrlen = ieee80211_anyhdrsize(mtod(m, void *));
+
+ /*
+ * Decrypt frame.
+ */
+ if (!cip->ic_decap(key, m, hdrlen)) {
+ printf("FAIL: wep decap failed\n");
+ cmpfail(mtod(m, const void *), m->m_pkthdr.len,
+ t->plaintext, t->plaintext_len);
+ goto bad;
+ }
+ /*
+ * Verify: frame length, frame contents.
+ */
+ if (m->m_pkthdr.len != t->plaintext_len) {
+ printf("FAIL: decap botch; length mismatch\n");
+ cmpfail(mtod(m, const void *), m->m_pkthdr.len,
+ t->plaintext, t->plaintext_len);
+ goto bad;
+ } else if (memcmp(mtod(m, const void *), t->plaintext, t->plaintext_len)) {
+ printf("FAIL: decap botch; data does not compare\n");
+ cmpfail(mtod(m, const void *), m->m_pkthdr.len,
+ t->plaintext, t->plaintext_len);
+ goto bad;
+ }
+
+ /*
+ * Encrypt frame.
+ */
+ ctx = (struct wep_ctx_hw *) key->wk_private;
+ ctx->wc_vap = vap;
+ ctx->wc_ic = vap->iv_ic;
+ memcpy(&ctx->wc_iv, t->iv, sizeof(t->iv)); /* for encap/encrypt */
+ if (!cip->ic_encap(key, m)) {
+ printf("FAIL: wep encap failed\n");
+ goto bad;
+ }
+ /*
+ * Verify: frame length, frame contents.
+ */
+ if (m->m_pkthdr.len != t->encrypted_len) {
+ printf("FAIL: encap data length mismatch\n");
+ cmpfail(mtod(m, const void *), m->m_pkthdr.len,
+ t->encrypted, t->encrypted_len);
+ goto bad;
+ } else if (memcmp(mtod(m, const void *), t->encrypted, m->m_pkthdr.len)) {
+ printf("FAIL: encrypt data does not compare\n");
+ cmpfail(mtod(m, const void *), m->m_pkthdr.len,
+ t->encrypted, t->encrypted_len);
+ dumpdata("Plaintext", t->plaintext, t->plaintext_len);
+ goto bad;
+ }
+ m_freem(m);
+ ieee80211_crypto_delkey(vap, key);
+ printf("PASS\n");
+ return 1;
+bad:
+ if (m != NULL)
+ m_freem(m);
+ ieee80211_crypto_delkey(vap, key);
+ return 0;
+}
+
+/*
+ * Module glue.
+ */
+
+static int tests = -1;
+static int debug = 0;
+
+static int
+init_crypto_wep_test(void)
+{
+ struct ieee80211com ic;
+ struct ieee80211vap vap;
+ struct ifnet ifp;
+ int i, pass, total;
+
+ memset(&ic, 0, sizeof(ic));
+ memset(&vap, 0, sizeof(vap));
+ memset(&ifp, 0, sizeof(ifp));
+
+ ieee80211_crypto_attach(&ic);
+
+ /* some minimal initialization */
+ strncpy(ifp.if_xname, "test_ccmp", sizeof(ifp.if_xname));
+ vap.iv_ic = &ic;
+ vap.iv_ifp = &ifp;
+ if (debug)
+ vap.iv_debug = IEEE80211_MSG_CRYPTO;
+ ieee80211_crypto_vattach(&vap);
+
+ pass = 0;
+ total = 0;
+ for (i = 0; i < nitems(weptests); i++)
+ if (tests & (1<<i)) {
+ total++;
+ pass += runtest(&vap, &weptests[i]);
+ }
+ printf("%u of %u 802.11i WEP test vectors passed\n", pass, total);
+
+ ieee80211_crypto_vdetach(&vap);
+ ieee80211_crypto_detach(&ic);
+
+ return (pass == total ? 0 : -1);
+}
+
+static int
+test_wep_modevent(module_t mod, int type, void *unused)
+{
+ switch (type) {
+ case MOD_LOAD:
+ (void) init_crypto_wep_test();
+ return 0;
+ case MOD_UNLOAD:
+ return 0;
+ }
+ return EINVAL;
+}
+
+static moduledata_t test_wep_mod = {
+ "test_wep",
+ test_wep_modevent,
+ 0
+};
+DECLARE_MODULE(test_wep, test_wep_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
+MODULE_VERSION(test_wep, 1);
+MODULE_DEPEND(test_wep, wlan, 1, 1, 1);