#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>
static const u_int8_t test1_key[] = {
0x30, 0x31, 0x32, 0x33, 0x34,
};
static const u_int8_t test1_plaintext[] = {
0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28,
0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08,
0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33,
0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00,
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[] = {
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,
};
#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 {
struct ieee80211vap *wc_vap;
struct ieee80211com *wc_ic;
uint32_t wc_iv;
};
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);
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;
}
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 *));
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;
}
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;
}
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));
if (!cip->ic_encap(key, m)) {
printf("FAIL: wep encap failed\n");
goto bad;
}
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;
}
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);
strncpy(ifp.if_xname, "test_ccmp", sizeof(ifp.if_xname));
vap.iv_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);