Ejemplo n.º 1
0
void
wep_dump(struct ieee80211_key *k, wbuf_t wbuf, int hdrlen)
{
	struct ieee80211_frame *wh;
    	struct wep_ctx *ctx = k->wk_private;
    	struct ieee80211vap *vap = ctx->wc_vap;
	unsigned int iv,idx,icv;
	unsigned char *ptr;
	unsigned char kbuf[64];


	wh = (struct ieee80211_frame *)wbuf_header(wbuf);
	ptr = (unsigned char*)wh;       

	idx = iv = 0;
	memcpy(&iv, ptr+hdrlen, 3);
	idx = ptr[hdrlen+3];
	memcpy(&icv, ptr+wbuf_get_pktlen(wbuf)-4, 4);

	memcpy(kbuf, k->wk_key, k->wk_keylen);
 
	IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1,
            "%s and seq=%02x-%02x\n", "addr1", wh->i_seq[0], wh->i_seq[1]);
	IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr3,
            "%s", "addr3");
	IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
            "IV=%08x idx=%d ICV=%08x, hdrlen=%d",iv, idx&0xff, icv, hdrlen);

	printk("key dump:len=%d\n", k->wk_keylen);
	dump_hex_buf(kbuf, (int)k->wk_keylen);
	printk("packet dump:pktlen=%d,len=%d\n", wbuf_get_pktlen(wbuf), wbuf_get_len(wbuf));
	dump_hex_buf((uint8_t*)ptr/*wbuf_raw_data(wbuf)*/, (int)wbuf_get_pktlen(wbuf));
}
Ejemplo n.º 2
0
int
ccmp_encrypt(struct ieee80211_key *key, wbuf_t wbuf0, int hdrlen, int mfp)
{
    struct ccmp_ctx *ctx = key->wk_private;
    struct ieee80211_frame *wh;
    wbuf_t wbuf = wbuf0;
    int data_len, i, space;
    uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN], b[AES_BLOCK_LEN],
        e[AES_BLOCK_LEN], s0[AES_BLOCK_LEN];
    uint8_t *pos;

    ctx->cc_vap->iv_stats.is_crypto_ccmp++;
    wh = (struct ieee80211_frame *)wbuf_header(wbuf);
    data_len = wbuf_get_pktlen(wbuf) - (hdrlen + ccmp.ic_header);
    ccmp_init_blocks(&ctx->cc_aes, wh, key->wk_keytsc,
                     data_len, b0, aad, b, s0, mfp);

    i = 1;
    pos = (u_int8_t *)wbuf_header(wbuf) + hdrlen + ccmp.ic_header;
    /* NB: assumes header is entirely in first mbuf */
    space = wbuf_get_pktlen(wbuf) - (hdrlen + ccmp.ic_header);
    for (;;) {
        if (space > data_len)
            space = data_len;
        /*
         * Do full blocks.
         */
        while (space >= AES_BLOCK_LEN) {
            CCMP_ENCRYPT(i, b, b0, pos, e, AES_BLOCK_LEN);
            pos += AES_BLOCK_LEN, space -= AES_BLOCK_LEN;
            data_len -= AES_BLOCK_LEN;
            i++;
        }
        if (data_len <= 0)		/* no more data */
            break;
        wbuf = wbuf_next(wbuf);
        if (wbuf == NULL) {		/* last buffer */
            if (space != 0) {
                /*
                 * Short last block.
                 */
                CCMP_ENCRYPT(i, b, b0, pos, e, space);
            }
            break;
        }
#if 1 /* assume only one chunk */
        break;
#else
        if (space != 0) {
            uint8_t *pos_next;
            int space_next;
            int len, dl, sp;
            wbuf_t wbufi_new;

            /*
             * Block straddles one or more mbufs, gather data
             * into the block buffer b, apply the cipher, then
             * scatter the results back into the mbuf chain.
             * The buffer will automatically get space bytes
             * of data at offset 0 copied in+out by the
             * CCMP_ENCRYPT request so we must take care of
             * the remaining data.
             */
            wbuf_new = wbuf;
            dl = data_len;
            sp = space;
            for (;;) {
                pos_next = (u_int8_t *)wbuf_header(wbuf_new);
                len = min(dl, AES_BLOCK_LEN);
                space_next = len > sp ? len - sp : 0;
                if (wbuf_get_len(wbuf_new) >= space_next) {
                    /*
                     * This mbuf has enough data; just grab
                     * what we need and stop.
                     */
                    xor_block(b+sp, pos_next, space_next);
                    break;
                }
                /*
                 * This mbuf's contents are insufficient,
                 * take 'em all and prepare to advance to
                 * the next mbuf.
                 */
                xor_block(b+sp, pos_next, n->m_len);
                sp += wbuf_get_len(wbuf_new), dl -= wbuf_get_len(wbuf_new);
                wbuf_next = m_next;
                if (n == NULL)
                    break;
            }

            CCMP_ENCRYPT(i, b, b0, pos, e, space);

            /* NB: just like above, but scatter data to mbufs */
            dl = data_len;
            sp = space;
            for (;;) {
                pos_next = mtod(m, uint8_t *);
                len = min(dl, AES_BLOCK_LEN);
                space_next = len > sp ? len - sp : 0;
                if (m->m_len >= space_next) {
                    xor_block(pos_next, e+sp, space_next);
                    break;
                }
                xor_block(pos_next, e+sp, m->m_len);
                sp += m->m_len, dl -= m->m_len;
                m = m->m_next;
                if (m == NULL)
                    goto done;
            }
            /*
             * Do bookkeeping.  m now points to the last mbuf
             * we grabbed data from.  We know we consumed a
             * full block of data as otherwise we'd have hit
             * the end of the mbuf chain, so deduct from data_len.
             * Otherwise advance the block number (i) and setup
             * pos+space to reflect contents of the new mbuf.
             */
            data_len -= AES_BLOCK_LEN;
            i++;
            pos = pos_next + space_next;
            space = m->m_len - space_next;
        } else {
Ejemplo n.º 3
0
/*
 * Save an outbound packet for a node in power-save sleep state.
 * The new packet is placed on the node's saved queue, and the TIM
 * is changed, if necessary.
 */
void
ieee80211_node_saveq_queue(struct ieee80211_node *ni, wbuf_t wbuf, u_int8_t frame_type)
{
    struct ieee80211vap *vap = ni->ni_vap;
    struct ieee80211com *ic = ni->ni_ic;
    int qlen, age;
    struct node_powersave_queue *dataq,*mgtq,*psq;
    struct ieee80211_tx_status ts;

#if LMAC_SUPPORT_POWERSAVE_QUEUE
    /* mark the frame and will give to ath layer */
    wbuf_set_legacy_ps(wbuf);
    if (ic->ic_get_lmac_pwrsaveq_len(ic, ni, 0) == 0 && vap->iv_set_tim != NULL) {
        vap->iv_set_tim(ni, 1, false);
    }

    return;
#endif

    dataq = IEEE80211_NODE_SAVEQ_DATAQ(ni);
    mgtq  = IEEE80211_NODE_SAVEQ_MGMTQ(ni);


    IEEE80211_NODE_SAVEQ_LOCK(dataq);
    IEEE80211_NODE_SAVEQ_LOCK(mgtq);

    if (frame_type == IEEE80211_FC0_TYPE_MGT) {
        psq = mgtq;
    } else {
        psq = dataq;
    }

    if (IEEE80211_NODE_SAVEQ_FULL(psq)) {
        IEEE80211_NODE_SAVEQ_UNLOCK(mgtq);
        IEEE80211_NODE_SAVEQ_UNLOCK(dataq);
        IEEE80211_NOTE(vap, IEEE80211_MSG_ANY, ni,
                       "%s pwr save q: overflow, drops (size %d) \n",
                       (psq == dataq) ? "data" : "mgt",
                       IEEE80211_PS_MAX_QUEUE);
        IEEE80211_NODE_STAT(ni,psq_drops);
#ifdef IEEE80211_DEBUG
        if (ieee80211_msg_dumppkts(vap))
            ieee80211_dump_pkt(ni->ni_ic, wtod(wbuf, caddr_t), wbuf_get_len(wbuf), -1, -1);
#endif
        ts.ts_flags = IEEE80211_TX_ERROR;
        ieee80211_release_wbuf(ni,wbuf, &ts);
        return;

    }
    /*
     * special handling of frames with PS = 1.
     */
    ieee80211_node_saveq_handle_ps_frames(ni,wbuf,frame_type);

    /*
     * Tag the frame with it's expiry time and insert
     * it in the queue.  The aging interval is 4 times
     * the listen interval specified by the station.
     * Frames that sit around too long are reclaimed
     * using this information.
     */
    age = ((ni->ni_intval * ic->ic_lintval) << 2) >> 10; /* TU -> secs */
    /*
     * Note: our aging algorithm is not working well. In fact, due to the long interval
     * when the aging algorithm is called (IEEE80211_INACT_WAIT is 15 secs), we depend on
     * the associated station node to be disassociated to clear its stale frames. However,
     * as a temporary fix, I will make sure that the age is at least greater than
     * IEEE80211_INACT_WAIT. Otherwise, we will discard all frames in ps queue even though
     * it is just queued.
    */
    if (age < IEEE80211_INACT_WAIT) {
        IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                       "%s Note: increased age from %d to %d secs.\n",
                       __func__, age, IEEE80211_INACT_WAIT);
        age = IEEE80211_INACT_WAIT;
    }
    IEEE80211_NODE_SAVEQ_ENQUEUE(psq, wbuf, qlen, age);
    /*
     * calculate the combined queue length of management and data queues.
     */
    qlen = IEEE80211_NODE_SAVEQ_QLEN(dataq);
    qlen += IEEE80211_NODE_SAVEQ_QLEN(mgtq);

    IEEE80211_NODE_SAVEQ_UNLOCK(mgtq);
    IEEE80211_NODE_SAVEQ_UNLOCK(dataq);

    IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                   "%s pwr queue:save frame, %u now queued \n", (psq == dataq) ? "data" : "mgt" ,qlen);
    if (qlen == 1 && vap->iv_set_tim != NULL)
        vap->iv_set_tim(ni, 1, false);
}