xref: /freebsd/tools/regression/net80211/tkip/test_tkip.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
12efe996bSSam Leffler /*-
22efe996bSSam Leffler  * Copyright (c) 2004 Sam Leffler, Errno Consulting
32efe996bSSam Leffler  * All rights reserved.
42efe996bSSam Leffler  *
52efe996bSSam Leffler  * Redistribution and use in source and binary forms, with or without
62efe996bSSam Leffler  * modification, are permitted provided that the following conditions
72efe996bSSam Leffler  * are met:
82efe996bSSam Leffler  * 1. Redistributions of source code must retain the above copyright
92efe996bSSam Leffler  *    notice, this list of conditions and the following disclaimer.
102efe996bSSam Leffler  * 2. Redistributions in binary form must reproduce the above copyright
112efe996bSSam Leffler  *    notice, this list of conditions and the following disclaimer in the
122efe996bSSam Leffler  *    documentation and/or other materials provided with the distribution.
132efe996bSSam Leffler  * 3. The name of the author may not be used to endorse or promote products
142efe996bSSam Leffler  *    derived from this software without specific prior written permission.
152efe996bSSam Leffler  *
162efe996bSSam Leffler  * Alternatively, this software may be distributed under the terms of the
172efe996bSSam Leffler  * GNU General Public License ("GPL") version 2 as published by the Free
182efe996bSSam Leffler  * Software Foundation.
192efe996bSSam Leffler  *
202efe996bSSam Leffler  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
212efe996bSSam Leffler  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
222efe996bSSam Leffler  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
232efe996bSSam Leffler  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
242efe996bSSam Leffler  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
252efe996bSSam Leffler  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
262efe996bSSam Leffler  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
272efe996bSSam Leffler  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
282efe996bSSam Leffler  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
292efe996bSSam Leffler  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
302efe996bSSam Leffler  */
312efe996bSSam Leffler 
322efe996bSSam Leffler /*
332efe996bSSam Leffler  * TKIP test module.
342efe996bSSam Leffler  */
352efe996bSSam Leffler #include <sys/param.h>
362efe996bSSam Leffler #include <sys/kernel.h>
372efe996bSSam Leffler #include <sys/systm.h>
382efe996bSSam Leffler #include <sys/mbuf.h>
392efe996bSSam Leffler #include <sys/module.h>
402efe996bSSam Leffler 
412efe996bSSam Leffler #include <sys/socket.h>
422efe996bSSam Leffler 
432efe996bSSam Leffler #include <net/if.h>
44*3c64fc9cSAndriy Voskoboinyk #include <net/if_var.h>
452efe996bSSam Leffler #include <net/if_media.h>
462efe996bSSam Leffler 
472efe996bSSam Leffler #include <net80211/ieee80211_var.h>
482efe996bSSam Leffler 
492efe996bSSam Leffler /*
502efe996bSSam Leffler Key	12 34 56 78 90 12 34 56 78 90 12 34 56 78 90 12
512efe996bSSam Leffler 	34 56 78 90 12 34 56 78 90 12 34 56 78 90 12 34
522efe996bSSam Leffler PN	0x000000000001
532efe996bSSam Leffler IV	00 20 01 20 00 00 00 00
542efe996bSSam Leffler Phase1	bb 58 07 1f 9e 93 b4 38 25 4b
552efe996bSSam Leffler Phase2	00 20 01 4c fe 67 be d2 7c 86 7b 1b f8 02 8b 1c
562efe996bSSam Leffler */
572efe996bSSam Leffler 
582efe996bSSam Leffler static const u_int8_t test1_key[] = {
592efe996bSSam Leffler 	0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12,
602efe996bSSam Leffler 	0x34, 0x56, 0x78, 0x90, 0x12,
612efe996bSSam Leffler 
622efe996bSSam Leffler 	0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78,		/* TX MIC */
632efe996bSSam Leffler 	/*
642efe996bSSam Leffler 	 * NB: 11i test vector specifies a RX MIC key different
652efe996bSSam Leffler 	 *     from the TX key.  But this doesn't work to enmic,
662efe996bSSam Leffler 	 *     encrypt, then decrypt, demic.  So instead we use
672efe996bSSam Leffler 	 *     the same key for doing the MIC in each direction.
682efe996bSSam Leffler 	 *
692efe996bSSam Leffler 	 * XXX need additional vectors to test alternate MIC keys
702efe996bSSam Leffler 	 */
712efe996bSSam Leffler #if 0
722efe996bSSam Leffler 	0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34,		/* 11i RX MIC */
732efe996bSSam Leffler #else
742efe996bSSam Leffler 	0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78,		/* TX copy */
752efe996bSSam Leffler #endif
762efe996bSSam Leffler };
772efe996bSSam Leffler static const u_int8_t test1_phase1[] = {
782efe996bSSam Leffler 	0xbb, 0x58, 0x07, 0x1f, 0x9e, 0x93, 0xb4, 0x38, 0x25, 0x4b
792efe996bSSam Leffler };
802efe996bSSam Leffler static const u_int8_t test1_phase2[] = {
812efe996bSSam Leffler 	0x00, 0x20, 0x01, 0x4c, 0xfe, 0x67, 0xbe, 0xd2, 0x7c, 0x86,
822efe996bSSam Leffler 	0x7b, 0x1b, 0xf8, 0x02, 0x8b, 0x1c,
832efe996bSSam Leffler };
842efe996bSSam Leffler 
852efe996bSSam Leffler /* Plaintext MPDU with MIC */
862efe996bSSam Leffler static const u_int8_t test1_plaintext[] = {
872efe996bSSam Leffler 0x08,0x42,0x2c,0x00,0x02,0x03,0x04,0x05,0x06,0x08,0x02,0x03,0x04,0x05,0x06,0x07,
882efe996bSSam Leffler 0x02,0x03,0x04,0x05,0x06,0x07,0xd0,0x02,
892efe996bSSam Leffler 0xaa,0xaa,0x03,0x00,0x00,0x00,0x08,0x00,0x45,0x00,0x00,0x54,0x00,0x00,0x40,0x00,
902efe996bSSam Leffler 0x40,0x01,0xa5,0x55,0xc0,0xa8,0x0a,0x02,0xc0,0xa8,0x0a,0x01,0x08,0x00,0x3a,0xb0,
912efe996bSSam Leffler 0x00,0x00,0x00,0x00,0xcd,0x4c,0x05,0x00,0x00,0x00,0x00,0x00,0x08,0x09,0x0a,0x0b,
922efe996bSSam Leffler 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,
932efe996bSSam Leffler 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,
942efe996bSSam Leffler 0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
952efe996bSSam Leffler /* MIC */ 0x68,0x81,0xa3,0xf3,0xd6,0x48,0xd0,0x3c
962efe996bSSam Leffler };
972efe996bSSam Leffler 
982efe996bSSam Leffler /* Encrypted MPDU with MIC and ICV */
992efe996bSSam Leffler static const u_int8_t test1_encrypted[] = {
1002efe996bSSam Leffler 0x08,0x42,0x2c,0x00,0x02,0x03,0x04,0x05,0x06,0x08,0x02,0x03,0x04,0x05,0x06,0x07,
1012efe996bSSam Leffler 0x02,0x03,0x04,0x05,0x06,0x07,0xd0,0x02,0x00,0x20,0x01,0x20,0x00,0x00,0x00,0x00,
1022efe996bSSam Leffler 0xc0,0x0e,0x14,0xfc,0xe7,0xcf,0xab,0xc7,0x75,0x47,0xe6,0x66,0xe5,0x7c,0x0d,0xac,
1032efe996bSSam Leffler 0x70,0x4a,0x1e,0x35,0x8a,0x88,0xc1,0x1c,0x8e,0x2e,0x28,0x2e,0x38,0x01,0x02,0x7a,
1042efe996bSSam Leffler 0x46,0x56,0x05,0x5e,0xe9,0x3e,0x9c,0x25,0x47,0x02,0xe9,0x73,0x58,0x05,0xdd,0xb5,
1052efe996bSSam Leffler 0x76,0x9b,0xa7,0x3f,0x1e,0xbb,0x56,0xe8,0x44,0xef,0x91,0x22,0x85,0xd3,0xdd,0x6e,
1062efe996bSSam Leffler 0x54,0x1e,0x82,0x38,0x73,0x55,0x8a,0xdb,0xa0,0x79,0x06,0x8a,0xbd,0x7f,0x7f,0x50,
1072efe996bSSam Leffler 0x95,0x96,0x75,0xac,0xc4,0xb4,0xde,0x9a,0xa9,0x9c,0x05,0xf2,0x89,0xa7,0xc5,0x2f,
1082efe996bSSam Leffler 0xee,0x5b,0xfc,0x14,0xf6,0xf8,0xe5,0xf8
1092efe996bSSam Leffler };
1102efe996bSSam Leffler 
1112efe996bSSam Leffler #define	TEST(n,name,cipher,keyix,pn) { \
1122efe996bSSam Leffler 	name, IEEE80211_CIPHER_##cipher,keyix, pn##LL, \
1132efe996bSSam Leffler 	test##n##_key,   sizeof(test##n##_key), \
1142efe996bSSam Leffler 	test##n##_phase1,   sizeof(test##n##_phase1), \
1152efe996bSSam Leffler 	test##n##_phase2,   sizeof(test##n##_phase2), \
1162efe996bSSam Leffler 	test##n##_plaintext, sizeof(test##n##_plaintext), \
1172efe996bSSam Leffler 	test##n##_encrypted, sizeof(test##n##_encrypted) \
1182efe996bSSam Leffler }
1192efe996bSSam Leffler 
1202efe996bSSam Leffler struct ciphertest {
1212efe996bSSam Leffler 	const char	*name;
1222efe996bSSam Leffler 	int		cipher;
1232efe996bSSam Leffler 	int		keyix;
1242efe996bSSam Leffler 	u_int64_t	pn;
1252efe996bSSam Leffler 	const u_int8_t	*key;
1262efe996bSSam Leffler 	size_t		key_len;
1272efe996bSSam Leffler 	const u_int8_t	*phase1;
1282efe996bSSam Leffler 	size_t		phase1_len;
1292efe996bSSam Leffler 	const u_int8_t	*phase2;
1302efe996bSSam Leffler 	size_t		phase2_len;
1312efe996bSSam Leffler 	const u_int8_t	*plaintext;
1322efe996bSSam Leffler 	size_t		plaintext_len;
1332efe996bSSam Leffler 	const u_int8_t	*encrypted;
1342efe996bSSam Leffler 	size_t		encrypted_len;
1352efe996bSSam Leffler } tkiptests[] = {
1362efe996bSSam Leffler 	TEST(1, "TKIP test mpdu 1", TKIP, 0, 0),
1372efe996bSSam Leffler };
1382efe996bSSam Leffler 
1392efe996bSSam Leffler struct tkip_ctx {
1402efe996bSSam Leffler 	struct ieee80211com *tc_ic;	/* for diagnostics */
1412efe996bSSam Leffler 
1422efe996bSSam Leffler 	uint16_t tx_ttak[5];
1432efe996bSSam Leffler 	uint8_t	tx_rc4key[16];
1442efe996bSSam Leffler 
1452efe996bSSam Leffler 	uint16_t rx_ttak[5];
1462efe996bSSam Leffler 	int	rx_phase1_done;
1472efe996bSSam Leffler 	uint8_t	rx_rc4key[16];
1482efe996bSSam Leffler 	uint64_t rx_rsc;		/* held until MIC verified */
1492efe996bSSam Leffler };
1502efe996bSSam Leffler 
1512efe996bSSam Leffler static void
dumpdata(const char * tag,const void * p,size_t len)1522efe996bSSam Leffler dumpdata(const char *tag, const void *p, size_t len)
1532efe996bSSam Leffler {
1542efe996bSSam Leffler 	int i;
1552efe996bSSam Leffler 
1562efe996bSSam Leffler 	printf("%s: 0x%p len %u", tag, p, len);
1572efe996bSSam Leffler 	for (i = 0; i < len; i++) {
1582efe996bSSam Leffler 		if ((i % 16) == 0)
1592efe996bSSam Leffler 			printf("\n%03d:", i);
1602efe996bSSam Leffler 		printf(" %02x", ((const u_int8_t *)p)[i]);
1612efe996bSSam Leffler 	}
1622efe996bSSam Leffler 	printf("\n");
1632efe996bSSam Leffler }
1642efe996bSSam Leffler 
1652efe996bSSam Leffler static void
cmpfail(const void * gen,size_t genlen,const void * ref,size_t reflen)1662efe996bSSam Leffler cmpfail(const void *gen, size_t genlen, const void *ref, size_t reflen)
1672efe996bSSam Leffler {
1682efe996bSSam Leffler 	int i;
1692efe996bSSam Leffler 
1702efe996bSSam Leffler 	for (i = 0; i < genlen; i++)
1712efe996bSSam Leffler 		if (((const u_int8_t *)gen)[i] != ((const u_int8_t *)ref)[i]) {
1722efe996bSSam Leffler 			printf("first difference at byte %u\n", i);
1732efe996bSSam Leffler 			break;
1742efe996bSSam Leffler 		}
1752efe996bSSam Leffler 	dumpdata("Generated", gen, genlen);
1762efe996bSSam Leffler 	dumpdata("Reference", ref, reflen);
1772efe996bSSam Leffler }
1782efe996bSSam Leffler 
1792efe996bSSam Leffler static int
runtest(struct ieee80211vap * vap,struct ciphertest * t)180*3c64fc9cSAndriy Voskoboinyk runtest(struct ieee80211vap *vap, struct ciphertest *t)
1812efe996bSSam Leffler {
1822efe996bSSam Leffler 	struct tkip_ctx *ctx;
183*3c64fc9cSAndriy Voskoboinyk 	struct ieee80211_key *key = &vap->iv_nw_keys[t->keyix];
1842efe996bSSam Leffler 	struct mbuf *m = NULL;
1852efe996bSSam Leffler 	const struct ieee80211_cipher *cip;
1862efe996bSSam Leffler 	u_int len;
187*3c64fc9cSAndriy Voskoboinyk 	int hdrlen;
1882efe996bSSam Leffler 
1892efe996bSSam Leffler 	printf("%s: ", t->name);
1902efe996bSSam Leffler 
1912efe996bSSam Leffler 	/*
1922efe996bSSam Leffler 	 * Setup key.
1932efe996bSSam Leffler 	 */
194*3c64fc9cSAndriy Voskoboinyk 	memset(key, 0, sizeof(*key));
195*3c64fc9cSAndriy Voskoboinyk 	key->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
196*3c64fc9cSAndriy Voskoboinyk 	key->wk_cipher = &ieee80211_cipher_none;
197*3c64fc9cSAndriy Voskoboinyk 	if (!ieee80211_crypto_newkey(vap, t->cipher,
198*3c64fc9cSAndriy Voskoboinyk 	    IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, key)) {
1992efe996bSSam Leffler 		printf("FAIL: ieee80211_crypto_newkey failed\n");
2002efe996bSSam Leffler 		goto bad;
2012efe996bSSam Leffler 	}
2022efe996bSSam Leffler 
203*3c64fc9cSAndriy Voskoboinyk 	memcpy(key->wk_key, t->key, t->key_len);
204*3c64fc9cSAndriy Voskoboinyk 	key->wk_keylen = 128/NBBY;
205*3c64fc9cSAndriy Voskoboinyk 	memset(key->wk_keyrsc, 0, sizeof(key->wk_keyrsc));
206*3c64fc9cSAndriy Voskoboinyk 	key->wk_keytsc = t->pn;
207*3c64fc9cSAndriy Voskoboinyk 	if (!ieee80211_crypto_setkey(vap, key)) {
2082efe996bSSam Leffler 		printf("FAIL: ieee80211_crypto_setkey failed\n");
2092efe996bSSam Leffler 		goto bad;
2102efe996bSSam Leffler 	}
2112efe996bSSam Leffler 
2122efe996bSSam Leffler 	/*
2132efe996bSSam Leffler 	 * Craft frame from plaintext data.
2142efe996bSSam Leffler 	 */
215*3c64fc9cSAndriy Voskoboinyk 	cip = key->wk_cipher;
2162efe996bSSam Leffler 	m = m_getcl(M_NOWAIT, MT_HEADER, M_PKTHDR);
2172efe996bSSam Leffler 	m->m_data += cip->ic_header;
2182efe996bSSam Leffler 	len = t->plaintext_len - IEEE80211_WEP_MICLEN;
2192efe996bSSam Leffler 	memcpy(mtod(m, void *), t->plaintext, len);
2202efe996bSSam Leffler 	m->m_len = len;
2212efe996bSSam Leffler 	m->m_pkthdr.len = m->m_len;
222*3c64fc9cSAndriy Voskoboinyk 	hdrlen = ieee80211_anyhdrsize(mtod(m, void *));
2232efe996bSSam Leffler 
2242efe996bSSam Leffler 	/*
2252efe996bSSam Leffler 	 * Add MIC.
2262efe996bSSam Leffler 	 */
227*3c64fc9cSAndriy Voskoboinyk 	if (!ieee80211_crypto_enmic(vap, key, m, 1)) {
2282efe996bSSam Leffler 		printf("FAIL: tkip enmic failed\n");
2292efe996bSSam Leffler 		goto bad;
2302efe996bSSam Leffler 	}
2312efe996bSSam Leffler 	/*
2322efe996bSSam Leffler 	 * Verify: frame length, frame contents.
2332efe996bSSam Leffler 	 */
2342efe996bSSam Leffler 	if (m->m_pkthdr.len != t->plaintext_len) {
2352efe996bSSam Leffler 		printf("FAIL: enmic botch; length mismatch\n");
2362efe996bSSam Leffler 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
2372efe996bSSam Leffler 			t->plaintext, t->plaintext_len);
2382efe996bSSam Leffler 		goto bad;
2392efe996bSSam Leffler 	}
2402efe996bSSam Leffler 	if (memcmp(mtod(m, const void *), t->plaintext, t->plaintext_len)) {
2412efe996bSSam Leffler 		printf("FAIL: enmic botch\n");
2422efe996bSSam Leffler 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
2432efe996bSSam Leffler 			t->plaintext, t->plaintext_len);
2442efe996bSSam Leffler 		goto bad;
2452efe996bSSam Leffler 	}
2462efe996bSSam Leffler 	/*
2472efe996bSSam Leffler 	 * Encrypt frame w/ MIC.
2482efe996bSSam Leffler 	 */
249*3c64fc9cSAndriy Voskoboinyk 	if (!cip->ic_encap(key, m)) {
2502efe996bSSam Leffler 		printf("FAIL: tkip encap failed\n");
2512efe996bSSam Leffler 		goto bad;
2522efe996bSSam Leffler 	}
2532efe996bSSam Leffler 	/*
2542efe996bSSam Leffler 	 * Verify: phase1, phase2, frame length, frame contents.
2552efe996bSSam Leffler 	 */
256*3c64fc9cSAndriy Voskoboinyk 	ctx = key->wk_private;
2572efe996bSSam Leffler 	if (memcmp(ctx->tx_ttak, t->phase1, t->phase1_len)) {
2582efe996bSSam Leffler 		printf("FAIL: encrypt phase1 botch\n");
2592efe996bSSam Leffler 		cmpfail(ctx->tx_ttak, sizeof(ctx->tx_ttak),
2602efe996bSSam Leffler 			t->phase1, t->phase1_len);
2612efe996bSSam Leffler 		goto bad;
2622efe996bSSam Leffler 	} else if (memcmp(ctx->tx_rc4key, t->phase2, t->phase2_len)) {
2632efe996bSSam Leffler 		printf("FAIL: encrypt phase2 botch\n");
2642efe996bSSam Leffler 		cmpfail(ctx->tx_rc4key, sizeof(ctx->tx_rc4key),
2652efe996bSSam Leffler 			t->phase2, t->phase2_len);
2662efe996bSSam Leffler 		goto bad;
2672efe996bSSam Leffler 	} else if (m->m_pkthdr.len != t->encrypted_len) {
2682efe996bSSam Leffler 		printf("FAIL: encrypt data length mismatch\n");
2692efe996bSSam Leffler 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
2702efe996bSSam Leffler 			t->encrypted, t->encrypted_len);
2712efe996bSSam Leffler 		goto bad;
2722efe996bSSam Leffler 	} else if (memcmp(mtod(m, const void *), t->encrypted, m->m_pkthdr.len)) {
2732efe996bSSam Leffler 		printf("FAIL: encrypt data does not compare\n");
2742efe996bSSam Leffler 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
2752efe996bSSam Leffler 			t->encrypted, t->encrypted_len);
2762efe996bSSam Leffler 		dumpdata("Plaintext", t->plaintext, t->plaintext_len);
2772efe996bSSam Leffler 		goto bad;
2782efe996bSSam Leffler 	}
2792efe996bSSam Leffler 
2802efe996bSSam Leffler 	/*
2812efe996bSSam Leffler 	 * Decrypt frame.
2822efe996bSSam Leffler 	 */
283*3c64fc9cSAndriy Voskoboinyk 	if (!cip->ic_decap(key, m, hdrlen)) {
2842efe996bSSam Leffler 		printf("tkip decap failed\n");
2852efe996bSSam Leffler 		/*
2862efe996bSSam Leffler 		 * Check reason for failure: phase1, phase2, frame data (ICV).
2872efe996bSSam Leffler 		 */
2882efe996bSSam Leffler 		if (memcmp(ctx->rx_ttak, t->phase1, t->phase1_len)) {
2892efe996bSSam Leffler 			printf("FAIL: decrypt phase1 botch\n");
2902efe996bSSam Leffler 			cmpfail(ctx->rx_ttak, sizeof(ctx->rx_ttak),
2912efe996bSSam Leffler 				t->phase1, t->phase1_len);
2922efe996bSSam Leffler 		} else if (memcmp(ctx->rx_rc4key, t->phase2, t->phase2_len)) {
2932efe996bSSam Leffler 			printf("FAIL: decrypt phase2 botch\n");
2942efe996bSSam Leffler 			cmpfail(ctx->rx_rc4key, sizeof(ctx->rx_rc4key),
2952efe996bSSam Leffler 				t->phase2, t->phase2_len);
2962efe996bSSam Leffler 		} else {
2972efe996bSSam Leffler 			printf("FAIL: decrypt data does not compare\n");
2982efe996bSSam Leffler 			cmpfail(mtod(m, const void *), m->m_pkthdr.len,
2992efe996bSSam Leffler 				t->plaintext, t->plaintext_len);
3002efe996bSSam Leffler 		}
3012efe996bSSam Leffler 		goto bad;
3022efe996bSSam Leffler 	}
3032efe996bSSam Leffler 	/*
3042efe996bSSam Leffler 	 * Verify: frame length, frame contents.
3052efe996bSSam Leffler 	 */
3062efe996bSSam Leffler 	if (m->m_pkthdr.len != t->plaintext_len) {
3072efe996bSSam Leffler 		printf("FAIL: decap botch; length mismatch\n");
3082efe996bSSam Leffler 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
3092efe996bSSam Leffler 			t->plaintext, t->plaintext_len);
3102efe996bSSam Leffler 		goto bad;
3112efe996bSSam Leffler 	}
3122efe996bSSam Leffler 	if (memcmp(mtod(m, const void *), t->plaintext, t->plaintext_len)) {
3132efe996bSSam Leffler 		printf("FAIL: decap botch; data does not compare\n");
3142efe996bSSam Leffler 		cmpfail(mtod(m, const void *), m->m_pkthdr.len,
3152efe996bSSam Leffler 			t->plaintext, t->plaintext_len);
3162efe996bSSam Leffler 		goto bad;
3172efe996bSSam Leffler 	}
3182efe996bSSam Leffler 	/*
3192efe996bSSam Leffler 	 * De-MIC decrypted frame.
3202efe996bSSam Leffler 	 */
321*3c64fc9cSAndriy Voskoboinyk 	if (!ieee80211_crypto_demic(vap, key, m, 1)) {
3222efe996bSSam Leffler 		printf("FAIL: tkip demic failed\n");
3232efe996bSSam Leffler 		goto bad;
3242efe996bSSam Leffler 	}
3252efe996bSSam Leffler 	/* XXX check frame length and contents... */
326*3c64fc9cSAndriy Voskoboinyk 	m_freem(m);
327*3c64fc9cSAndriy Voskoboinyk 	ieee80211_crypto_delkey(vap, key);
3282efe996bSSam Leffler 	printf("PASS\n");
3292efe996bSSam Leffler 	return 1;
3302efe996bSSam Leffler bad:
3312efe996bSSam Leffler 	if (m != NULL)
3322efe996bSSam Leffler 		m_freem(m);
333*3c64fc9cSAndriy Voskoboinyk 	ieee80211_crypto_delkey(vap, key);
3342efe996bSSam Leffler 	return 0;
3352efe996bSSam Leffler }
3362efe996bSSam Leffler 
3372efe996bSSam Leffler /*
3382efe996bSSam Leffler  * Module glue.
3392efe996bSSam Leffler  */
3402efe996bSSam Leffler 
3412efe996bSSam Leffler static	int debug = 0;
3422efe996bSSam Leffler static	int tests = -1;
3432efe996bSSam Leffler 
3442efe996bSSam Leffler static int
init_crypto_tkip_test(void)3452efe996bSSam Leffler init_crypto_tkip_test(void)
3462efe996bSSam Leffler {
3472efe996bSSam Leffler 	struct ieee80211com ic;
348*3c64fc9cSAndriy Voskoboinyk 	struct ieee80211vap vap;
349*3c64fc9cSAndriy Voskoboinyk 	struct ifnet ifp;
3502efe996bSSam Leffler 	int i, pass, total;
3512efe996bSSam Leffler 
3522efe996bSSam Leffler 	memset(&ic, 0, sizeof(ic));
353*3c64fc9cSAndriy Voskoboinyk 	memset(&vap, 0, sizeof(vap));
354*3c64fc9cSAndriy Voskoboinyk 	memset(&ifp, 0, sizeof(ifp));
355*3c64fc9cSAndriy Voskoboinyk 
3562efe996bSSam Leffler 	ieee80211_crypto_attach(&ic);
3572efe996bSSam Leffler 
358*3c64fc9cSAndriy Voskoboinyk 	/* some minimal initialization */
359*3c64fc9cSAndriy Voskoboinyk 	strncpy(ifp.if_xname, "test_ccmp", sizeof(ifp.if_xname));
360*3c64fc9cSAndriy Voskoboinyk 	vap.iv_ic = &ic;
361*3c64fc9cSAndriy Voskoboinyk 	vap.iv_ifp = &ifp;
362*3c64fc9cSAndriy Voskoboinyk 	if (debug)
363*3c64fc9cSAndriy Voskoboinyk 		vap.iv_debug = IEEE80211_MSG_CRYPTO;
364*3c64fc9cSAndriy Voskoboinyk 	ieee80211_crypto_vattach(&vap);
365*3c64fc9cSAndriy Voskoboinyk 
3662efe996bSSam Leffler 	pass = 0;
3672efe996bSSam Leffler 	total = 0;
368*3c64fc9cSAndriy Voskoboinyk 	for (i = 0; i < nitems(tkiptests); i++)
3692efe996bSSam Leffler 		if (tests & (1<<i)) {
3702efe996bSSam Leffler 			total++;
371*3c64fc9cSAndriy Voskoboinyk 			pass += runtest(&vap, &tkiptests[i]);
3722efe996bSSam Leffler 		}
3732efe996bSSam Leffler 	printf("%u of %u 802.11i TKIP test vectors passed\n", pass, total);
374*3c64fc9cSAndriy Voskoboinyk 
375*3c64fc9cSAndriy Voskoboinyk 	ieee80211_crypto_vdetach(&vap);
3762efe996bSSam Leffler 	ieee80211_crypto_detach(&ic);
377*3c64fc9cSAndriy Voskoboinyk 
3782efe996bSSam Leffler 	return (pass == total ? 0 : -1);
3792efe996bSSam Leffler }
3802efe996bSSam Leffler 
3812efe996bSSam Leffler static int
test_tkip_modevent(module_t mod,int type,void * unused)3822efe996bSSam Leffler test_tkip_modevent(module_t mod, int type, void *unused)
3832efe996bSSam Leffler {
3842efe996bSSam Leffler 	switch (type) {
3852efe996bSSam Leffler 	case MOD_LOAD:
3862efe996bSSam Leffler 		(void) init_crypto_tkip_test();
3872efe996bSSam Leffler 		return 0;
3882efe996bSSam Leffler 	case MOD_UNLOAD:
3892efe996bSSam Leffler 		return 0;
3902efe996bSSam Leffler 	}
3912efe996bSSam Leffler 	return EINVAL;
3922efe996bSSam Leffler }
3932efe996bSSam Leffler 
3942efe996bSSam Leffler static moduledata_t test_tkip_mod = {
3952efe996bSSam Leffler 	"test_tkip",
3962efe996bSSam Leffler 	test_tkip_modevent,
3979823d527SKevin Lo 	0
3982efe996bSSam Leffler };
3992efe996bSSam Leffler DECLARE_MODULE(test_tkip, test_tkip_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
4002efe996bSSam Leffler MODULE_VERSION(test_tkip, 1);
4012efe996bSSam Leffler MODULE_DEPEND(test_tkip, wlan, 1, 1, 1);
402