static int crypto_installkey(struct ieee80211_key *key, struct ieee80211vap *vap, 
					  struct ieee80211_node *ni)
{
    /* If a key cache slot is already allocated 
     * for this node use that, otherwise allocate
     * a new one.
     */
    IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: ni_rxkeyoff:%d, wk_keyidx:%d\n", 
	    __func__, ni->ni_rxkeyoff, key->wk_keyix);

    if (ni->ni_rxkeyoff)
        key->wk_keyix = ni->ni_rxkeyoff;
    else
        key->wk_keyix = IEEE80211_KEYIX_NONE;

    if(ieee80211_crypto_newkey(vap, IEEE80211_CIPHER_WEP,
                IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, key)) {

        if (!ieee80211_crypto_setkey(vap, key, ni->ni_macaddr, NULL)) {
		  IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: Couldn't set key, fatal.\n",
							__func__);
            return 0;
        }
        else {
            IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: Keyset successful on entry %d.\n",
							  __func__, key->wk_keyix);
            ni->ni_rxkeyoff = key->wk_keyix;
        }
    }
    return 1;
}
static int crypto_install_mcastkey(struct ieee80211_key *key, struct ieee80211vap *vap, 
                      struct ieee80211_node *ni)
{
    struct ieee80211_key *mc_key = &ni->ni_wep_mbssid.mcastkey;
    u_int8_t flags = /*IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV | */IEEE80211_KEY_GROUP;

    /* If a key cache slot is already allocated 
     * for this node use that, otherwise allocate
     * a new one.
     */
    mc_key->wk_keylen = key->wk_keylen;
    memset(&mc_key->wk_key, 0, sizeof(mc_key->wk_key));
    memcpy(&mc_key->wk_key, key->wk_key, key->wk_keylen);
    mc_key->wk_flags = flags;
    mc_key->wk_cipher = key->wk_cipher;

    if (ni->ni_wep_mbssid.mcastkey_idx)
        mc_key->wk_keyix = ni->ni_wep_mbssid.mcastkey_idx;
    else
        mc_key->wk_keyix = IEEE80211_KEYIX_NONE;

    if(ieee80211_crypto_newkey(vap, IEEE80211_CIPHER_WEP, flags, mc_key)) {

        if (!ieee80211_crypto_setkey(vap, mc_key, ni->ni_macaddr, NULL)) {
          IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: Couldn't set MCast key, fatal.\n",
                            __func__);
            return 0;
        }
        else {
            IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: MCast Keyset successful on entry %d.\n",
                              __func__, mc_key->wk_keyix);
            ni->ni_wep_mbssid.mcastkey_idx = mc_key->wk_keyix;
        }
    }

    return 1;
}
Beispiel #3
0
static int
runtest(struct ieee80211vap *vap, struct ciphertest *t)
{
	struct ieee80211_key *key;
	struct sk_buff *skb = NULL;
	const struct ieee80211_cipher *cip;
	u_int8_t mac[IEEE80211_ADDR_LEN];
	struct wep_ctx_hw *ctx;
	int hdrlen;

	printk("%s: ", t->name);

	if (!ieee80211_crypto_available(vap, t->cipher)) {
		printk("FAIL: ieee80211_crypto_available failed\n");
		return 0;
	}

	/*
	 * Setup key.
	 */
	key = &vap->iv_nw_keys[t->keyix];
	key->wk_keyix = t->keyix;
	if (!ieee80211_crypto_newkey(vap, t->cipher,
				     IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV,
				     key)) {
		printk("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, mac, NULL)) {
		printk("FAIL: ieee80211_crypto_setkey failed\n");
		goto bad;
	}
	cip = key->wk_cipher;

	/*
	 * Craft encrypted frame from known data.
	 */
	skb = ieee80211_dev_alloc_skb(t->encrypted_len);
	if (skb == NULL) {
		printk("FAIL: unable to allocate skbuff\n");
		goto bad;
	}
	memcpy(skb_put(skb, t->encrypted_len), t->encrypted, t->encrypted_len);

	/*
	 * Decrypt frame.
	 */
	hdrlen = ieee80211_hdrspace(vap->iv_ic, skb->data);
	if (!(*cip->ic_decap)(key, skb, hdrlen)) {
		printk("FAIL: wep decap failed\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, t->plaintext_len);
		goto bad;
	}
	/*
	 * Verify: frame length, frame contents.
	 */
	if (skb->len != t->plaintext_len) {
		printk("FAIL: decap botch; length mismatch\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, t->plaintext_len);
		goto bad;
	} else if (memcmp(skb->data, t->plaintext, t->plaintext_len)) {
		printk("FAIL: decap botch; data does not compare\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, sizeof(t->plaintext));
		goto bad;
	}

	/*
	 * Encrypt frame.
	 */
	ctx = (struct wep_ctx_hw *) key->wk_private;
	memcpy(&ctx->wc_iv, t->iv, sizeof(t->iv));	/* for encap/encrypt */
	if (!(*cip->ic_encap)(key, skb, t->keyix << 6)) {
		printk("FAIL: wep encap failed\n");
		goto bad;
	}
	/*
	 * Verify: frame length, frame contents.
	 */
	if (skb->len != t->encrypted_len) {
		printk("FAIL: encap data length mismatch\n");
		cmpfail(skb->data, skb->len,
			t->encrypted, t->encrypted_len);
		goto bad;
	} else if (memcmp(skb->data, t->encrypted, skb->len)) {
		printk("FAIL: encrypt data does not compare\n");
		cmpfail(skb->data, skb->len,
			t->encrypted, t->encrypted_len);
		dumpdata("Plaintext", t->plaintext, t->plaintext_len);
		goto bad;
	}
	if (skb != NULL)
		ieee80211_dev_kfree_skb(&skb);
	ieee80211_crypto_delkey(vap, key, NULL);
	printk("PASS\n");
	return 1;
bad:
	if (skb != NULL)
		ieee80211_dev_kfree_skb(&skb);
	ieee80211_crypto_delkey(vap, key, NULL);
	return 0;
}
Beispiel #4
0
int
runtest(struct ieee80211com *ic, struct ciphertest *t)
{
	struct ieee80211_key key;
	struct sk_buff *skb = NULL;
	const struct ieee80211_cipher *cip;
	u_int8_t mac[IEEE80211_ADDR_LEN];

	printk("%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(ic, t->cipher, &key)) {
		printk("FAIL: ieee80211_crypto_newkey failed\n");
		goto bad;
	}

	memcpy(key.wk_key, t->key, t->key_len);
	key.wk_keylen = t->key_len;
	key.wk_keyrsc = 0;
	key.wk_keytsc = t->pn-1;	/* PN-1 since we do encap */
	if (!ieee80211_crypto_setkey(ic, &key, mac)) {
		printk("FAIL: ieee80211_crypto_setkey failed\n");
		goto bad;
	}

	/*
	 * Craft frame from plaintext data.
	 */
	cip = key.wk_cipher;
	skb = dev_alloc_skb(t->plaintext_len +
			cip->ic_header + cip->ic_trailer);
	if (skb == NULL) {
		printk("FAIL: unable to allocate skbuff\n");
		goto bad;
	}
	skb_reserve(skb, cip->ic_header);
	memcpy(skb_put(skb, t->plaintext_len),
		t->plaintext, t->plaintext_len);

	/*
	 * Encrypt frame w/ MIC.
	 */
	if (!(*cip->ic_encap)(&key, skb, t->keyix<<6)) {
		printk("FAIL: ccmp encap failed\n");
		goto bad;
	}
	/*
	 * Verify: frame length, frame contents.
	 */
	if (skb->len != t->encrypted_len) {
		printk("FAIL: encap data length mismatch\n");
		cmpfail(skb->data, skb->len,
			t->encrypted, t->encrypted_len);
		goto bad;
	} else if (memcmp(skb->data, t->encrypted, skb->len)) {
		printk("FAIL: encrypt data does not compare\n");
		cmpfail(skb->data, skb->len,
			t->encrypted, t->encrypted_len);
		dumpdata("Plaintext", t->plaintext, t->plaintext_len);
		goto bad;
	}

	/*
	 * Decrypt frame; strip MIC.
	 */
	if (!(*cip->ic_decap)(&key, skb)) {
		printk("FAIL: ccmp decap failed\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, t->plaintext_len);
		goto bad;
	}
	/*
	 * Verify: frame length, frame contents.
	 */
	if (skb->len != t->plaintext_len) {
		printk("FAIL: decap botch; length mismatch\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, t->plaintext_len);
		goto bad;
	} else if (memcmp(skb->data, t->plaintext, t->plaintext_len)) {
		printk("FAIL: decap botch; data does not compare\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, sizeof(t->plaintext));
		goto bad;
	}
	dev_kfree_skb(skb);
	ieee80211_crypto_delkey(ic, &key);
	printk("PASS\n");
	return 1;
bad:
	if (skb != NULL)
		dev_kfree_skb(skb);
	ieee80211_crypto_delkey(ic, &key);
	return 0;
}
Beispiel #5
0
static int
runtest(struct ieee80211vap *vap, struct ciphertest *t)
{
	struct ieee80211_key *key;
	struct sk_buff *skb = NULL;
	const struct ieee80211_cipher *cip;
	u_int8_t mac[IEEE80211_ADDR_LEN];
	struct tkip_ctx *ctx;
	int hdrlen;

	printk("%s: ", t->name);

	if (!ieee80211_crypto_available(vap, t->cipher)) {
		printk("FAIL: ieee80211_crypto_available failed\n");
		return 0;
	}

	/*
	 * Setup key.
	 */
	key = &vap->iv_nw_keys[t->keyix];
	key->wk_keyix = t->keyix;
	if (!ieee80211_crypto_newkey(vap, t->cipher,
				     IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV,
				     key)) {
		printk("FAIL: ieee80211_crypto_newkey failed\n");
		goto bad;
	}

	memcpy(key->wk_key, t->key, t->key_len);
	key->wk_keylen = 128 / NBBY;
	memset(key->wk_keyrsc, 0, sizeof(key->wk_keyrsc));
	key->wk_keytsc = 0;
	if (!ieee80211_crypto_setkey(vap, key, mac, NULL)) {
		printk("FAIL: ieee80211_crypto_setkey failed\n");
		goto bad;
	}

	/*
	 * Craft frame from plaintext data.  Note that
	 * we leave the MIC off as we'll add it ourself
	 * and then check it against the reference data.
	 */
	cip = key->wk_cipher;
	skb = ieee80211_dev_alloc_skb(t->plaintext_len +
		cip->ic_miclen + cip->ic_header + cip->ic_trailer);
	if (skb == NULL) {
		printk("FAIL: unable to allocate skbuff\n");
		goto bad;
	}
	skb_reserve(skb, cip->ic_header);
	memcpy(skb_put(skb, t->plaintext_len - cip->ic_miclen),
		t->plaintext, t->plaintext_len - cip->ic_miclen);

	/*
	 * Add MIC.
	 */
	if (!ieee80211_crypto_enmic(vap, key, skb, 0)) {
		printk("FAIL: tkip enmic failed\n");
		goto bad;
	}
	/*
	 * Verify: frame length, frame contents.
	 */
	if (skb->len != t->plaintext_len) {
		printk("FAIL: enmic botch; length mismatch\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, t->plaintext_len);
		goto bad;
	}
	if (memcmp(skb->data, t->plaintext, t->plaintext_len)) {
		printk("FAIL: enmic botch\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, t->plaintext_len);
		goto bad;
	}
	/*
	 * Encrypt frame w/ MIC.
	 */
	if (!(*cip->ic_encap)(key, skb, t->keyix << 6)) {
		printk("FAIL: tkip encap failed\n");
		goto bad;
	}
	/*
	 * Verify: phase1, phase2, frame length, frame contents.
	 */
	ctx = key->wk_private;
	if (memcmp(ctx->tx_ttak, t->phase1, t->phase1_len)) {
		printk("FAIL: encrypt phase1 botch\n");
		cmpfail(ctx->tx_ttak, sizeof(ctx->tx_ttak),
			t->phase1, t->phase1_len);
		goto bad;
	} else if (memcmp(ctx->tx_rc4key, t->phase2, t->phase2_len)) {
		printf("FAIL: encrypt phase2 botch\n");
		cmpfail(ctx->tx_rc4key, sizeof(ctx->tx_rc4key),
			t->phase2, t->phase2_len);
		goto bad;
	} else if (skb->len != t->encrypted_len) {
		printk("FAIL: encrypt data length mismatch\n");
		cmpfail(skb->data, skb->len,
			t->encrypted, t->encrypted_len);
		goto bad;
	} else if (memcmp(skb->data, t->encrypted, skb->len)) {
		printk("FAIL: encrypt data does not compare\n");
		cmpfail(skb->data, skb->len,
			t->encrypted, t->encrypted_len);
		dumpdata("Plaintext", t->plaintext, t->plaintext_len);
		goto bad;
	}

	/*
	 * Decrypt frame.
	 */
	hdrlen = ieee80211_hdrspace(vap->iv_ic, skb->data);
	if (!(*cip->ic_decap)(key, skb, hdrlen)) {
		printk("FAIL: tkip decap failed\n");
		/*
		 * Check reason for failure: phase1, phase2, frame data (ICV).
		 */
		if (memcmp(ctx->rx_ttak, t->phase1, t->phase1_len)) {
			printk("decrypt phase1 botch\n");
			cmpfail(ctx->rx_ttak, sizeof(ctx->rx_ttak),
				t->phase1, t->phase1_len);
		} else if (memcmp(ctx->rx_rc4key, t->phase2, t->phase2_len)) {
			printf("decrypt phase2 botch\n");
			cmpfail(ctx->rx_rc4key, sizeof(ctx->rx_rc4key),
				t->phase2, t->phase2_len);
		} else {
			printk("decrypt data does not compare\n");
			cmpfail(skb->data, skb->len,
				t->plaintext, t->plaintext_len);
		}
		goto bad;
	}
	/*
	 * Verify: frame length, frame contents.
	 */
	if (skb->len != t->plaintext_len) {
		printk("FAIL: decap botch; length mismatch\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, t->plaintext_len);
		goto bad;
	}
	if (memcmp(skb->data, t->plaintext, t->plaintext_len)) {
		printk("FAIL: decap botch; data does not compare\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, t->plaintext_len);
		goto bad;
	}
	/*
	 * De-MIC decrypted frame.
	 */
	if (!ieee80211_crypto_demic(vap, key, skb, hdrlen, 0)) {
		printk("FAIL: tkip demic failed\n");
		goto bad;
	}
	/* XXX check frame length and contents... */
	ieee80211_dev_kfree_skb(&skb);
	ieee80211_crypto_delkey(vap, key, NULL);
	printk("PASS\n");
	return 1;
bad:
	if (skb != NULL)
		ieee80211_dev_kfree_skb(&skb);
	ieee80211_crypto_delkey(vap, key, NULL);
	return 0;
}
Beispiel #6
0
void
tkip_test(struct ieee80211com *ic)
{
	struct tkip_ctx *ctx;
	struct ieee80211_key key;
	struct sk_buff *skb = NULL;
	const struct ieee80211_cipher *cip;
	u_int8_t mac[IEEE80211_ADDR_LEN];

	/*
	 * 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(ic, IEEE80211_CIPHER_TKIP, &key)) {
		printk("ieee80211_crypto_newkey failed\n");
		goto bad;
	}

	memcpy(key.wk_key, ref_key, sizeof(ref_key));
	key.wk_keylen = 128 / NBBY;
	key.wk_keyrsc = 0;
	key.wk_keytsc = 0;
	if (!ieee80211_crypto_setkey(ic, &key, mac)) {
		printk("ieee80211_crypto_setkey failed\n");
		goto bad;
	}

	/*
	 * Craft frame from plaintext data.  Note that
	 * we leave the MIC off as we'll add it ourself
	 * and then check it against the reference data.
	 */
	cip = key.wk_cipher;
	skb = dev_alloc_skb(sizeof(ref_plaintext) +
		cip->ic_miclen + cip->ic_header + cip->ic_trailer);
	if (skb == NULL) {
		printk("unable to allocate skbuff\n");
		goto bad;
	}
	skb_reserve(skb, cip->ic_header);
	memcpy(skb_put(skb, sizeof(ref_plaintext) - cip->ic_miclen),
		ref_plaintext, sizeof(ref_plaintext) - cip->ic_miclen);

	/*
	 * Add MIC.
	 */
	if (!ieee80211_crypto_enmic(ic, &key, skb)) {
		printk("tkip enmic failed\n");
		goto bad;
	}
	/*
	 * Verify: frame length, frame contents.
	 */
	if (skb->len != sizeof(ref_plaintext)) {
		printk("enmic botch; length mismatch\n");
		cmpfail(skb->data, skb->len,
			ref_plaintext, sizeof(ref_plaintext));
		goto bad;
	}
	if (memcmp(skb->data, ref_plaintext, sizeof(ref_plaintext))) {
		printk("enmic botch\n");
		cmpfail(skb->data, skb->len,
			ref_plaintext, sizeof(ref_plaintext));
		goto bad;
	}
	/*
	 * Encrypt frame w/ MIC.
	 */
	if (!(*cip->ic_encap)(&key, skb, 0 << 6)) {
		printk("tkip encap failed\n");
		goto bad;
	}
	/*
	 * Verify: phase1, phase2, frame length, frame contents.
	 */
	ctx = key.wk_private;
	if (memcmp(ctx->tx_ttak, ref_phase1, sizeof(ref_phase1))) {
		printk("encrypt phase1 botch\n");
		cmpfail(ctx->tx_ttak, sizeof(ctx->tx_ttak),
			ref_phase1, sizeof(ref_phase1));
		goto bad;
	} else if (memcmp(ctx->tx_rc4key, ref_phase2, sizeof(ref_phase2))) {
		printf("encrypt phase2 botch\n");
		cmpfail(ctx->tx_rc4key, sizeof(ctx->tx_rc4key),
			ref_phase2, sizeof(ref_phase2));
		goto bad;
	} else if (skb->len != sizeof(ref_encrypted)) {
		printk("encrypt data length mismatch\n");
		cmpfail(skb->data, skb->len,
			ref_encrypted, sizeof(ref_encrypted));
		goto bad;
	} else if (memcmp(skb->data, ref_encrypted, skb->len)) {
		printk("encrypt data does not compare\n");
		cmpfail(skb->data, skb->len,
			ref_encrypted, sizeof(ref_encrypted));
		dumpdata("Plaintext", ref_plaintext, sizeof(ref_plaintext));
		goto bad;
	}

	/*
	 * Decrypt frame.
	 */
	if (!(*cip->ic_decap)(&key, skb)) {
		printk("tkip decap failed\n");
		/*
		 * Check reason for failure: phase1, phase2, frame data (ICV).
		 */
		if (memcmp(ctx->rx_ttak, ref_phase1, sizeof(ref_phase1))) {
			printk("decrypt phase1 botch\n");
			cmpfail(ctx->rx_ttak, sizeof(ctx->rx_ttak),
				ref_phase1, sizeof(ref_phase1));
		} else if (memcmp(ctx->rx_rc4key, ref_phase2, sizeof(ref_phase2))) {
			printf("decrypt phase2 botch\n");
			cmpfail(ctx->rx_rc4key, sizeof(ctx->rx_rc4key),
				ref_phase2, sizeof(ref_phase2));
		} else {
			printk("decrypt data does not compare\n");
			cmpfail(skb->data, skb->len,
				ref_plaintext, sizeof(ref_plaintext));
		}
		goto bad;
	}
	/*
	 * Verify: frame length, frame contents.
	 */
	if (skb->len != sizeof(ref_plaintext)) {
		printk("decap botch; length mismatch\n");
		cmpfail(skb->data, skb->len,
			ref_plaintext, sizeof(ref_plaintext));
		goto bad;
	}
	if (memcmp(skb->data, ref_plaintext, sizeof(ref_plaintext))) {
		printk("decap botch; data does not compare\n");
		cmpfail(skb->data, skb->len,
			ref_plaintext, sizeof(ref_plaintext));
		goto bad;
	}
	/*
	 * De-MIC decrypted frame.
	 */
	if (!ieee80211_crypto_demic(ic, &key, skb)) {
		printk("tkip demic failed\n");
		goto bad;
	}
	/* XXX check frame length and contents... */
	printk("802.11i TKIP test vectors passed\n");
bad:
	if (skb != NULL)
		dev_kfree_skb(skb);
	ieee80211_crypto_delkey(ic, &key);
}
Beispiel #7
0
static int
runtest(struct ieee80211vap *vap, struct ciphertest *t)
{
	struct ieee80211_key *key;
	struct sk_buff *skb = NULL;
	const struct ieee80211_cipher *cip;
	u_int8_t mac[IEEE80211_ADDR_LEN];
	int hdrlen;

	printk("%s: ", t->name);

	if (!ieee80211_crypto_available(vap, t->cipher)) {
		printk("FAIL: ieee80211_crypto_available failed\n");
		return 0;
	}

	/*
	 * Setup key.
	 */
	key = &vap->iv_nw_keys[t->keyix];
	key->wk_keyix = t->keyix;
	if (!ieee80211_crypto_newkey(vap, t->cipher,
				     IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV,
				     key)) {
		printk("FAIL: ieee80211_crypto_newkey failed\n");
		goto bad;
	}

	memcpy(key->wk_key, t->key, t->key_len);
	key->wk_keylen = t->key_len;
	memset(key->wk_keyrsc, 0, sizeof(key->wk_keyrsc));
	key->wk_keytsc = t->pn - 1;	/* PN-1 since we do encap */
	if (!ieee80211_crypto_setkey(vap, key, mac, NULL)) {
		printk("FAIL: ieee80211_crypto_setkey failed\n");
		goto bad;
	}

	/*
	 * Craft frame from plaintext data.
	 */
	cip = key->wk_cipher;
	skb = ieee80211_dev_alloc_skb(t->plaintext_len +
		cip->ic_header + cip->ic_trailer);
	if (skb == NULL) {
		printk("FAIL: unable to allocate skbuff\n");
		goto bad;
	}
	skb_reserve(skb, cip->ic_header);
	memcpy(skb_put(skb, t->plaintext_len), t->plaintext, t->plaintext_len);

	/*
	 * Encrypt frame w/ MIC.
	 */
	if (!(*cip->ic_encap)(key, skb, t->keyix << 6)) {
		printk("FAIL: ccmp encap failed\n");
		goto bad;
	}
	/*
	 * Verify: frame length, frame contents.
	 */
	if (skb->len != t->encrypted_len) {
		printk("FAIL: encap data length mismatch\n");
		cmpfail(skb->data, skb->len,
			t->encrypted, t->encrypted_len);
		goto bad;
	} else if (memcmp(skb->data, t->encrypted, skb->len)) {
		printk("FAIL: encrypt data does not compare\n");
		cmpfail(skb->data, skb->len,
			t->encrypted, t->encrypted_len);
		dumpdata("Plaintext", t->plaintext, t->plaintext_len);
		goto bad;
	}

	/*
	 * Decrypt frame; strip MIC.
	 */
	hdrlen = ieee80211_hdrspace(vap->iv_ic, skb->data);
	if (!(*cip->ic_decap)(key, skb, hdrlen)) {
		printk("FAIL: ccmp decap failed\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, t->plaintext_len);
		goto bad;
	}
	/*
	 * Verify: frame length, frame contents.
	 */
	if (skb->len != t->plaintext_len) {
		printk("FAIL: decap botch; length mismatch\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, t->plaintext_len);
		goto bad;
	} else if (memcmp(skb->data, t->plaintext, t->plaintext_len)) {
		printk("FAIL: decap botch; data does not compare\n");
		cmpfail(skb->data, skb->len,
			t->plaintext, sizeof(t->plaintext));
		goto bad;
	}
	ieee80211_dev_kfree_skb(&skb);
	ieee80211_crypto_delkey(vap, key, NULL);
	printk("PASS\n");
	return 1;
bad:
	if (skb != NULL)
		ieee80211_dev_kfree_skb(&skb);
	ieee80211_crypto_delkey(vap, key, NULL);
	return 0;
}