コード例 #1
0
INT AirPDcapCcmpDecrypt(
	UINT8 *m,
        gint mac_header_len,
	INT len,
	UCHAR TK1[16])
{
	PAIRPDCAP_MAC_FRAME wh;
	UINT8 aad[2 * AES_BLOCK_LEN];
	UINT8 b0[AES_BLOCK_LEN], b[AES_BLOCK_LEN], a[AES_BLOCK_LEN];
	UINT8 mic[AES_BLOCK_LEN];
	size_t data_len;
	UINT i;
	UINT8 *pos;
	UINT space;
	INT z = mac_header_len;
	rijndael_ctx key;
	UINT64 PN;
	UINT8 *ivp=m+z;

	PN = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);

	/* freebsd	*/
	rijndael_set_key(&key, TK1, 128);
	wh = (PAIRPDCAP_MAC_FRAME )m;
	data_len = len - (z + AIRPDCAP_CCMP_HEADER+AIRPDCAP_CCMP_TRAILER);
	if (data_len < 1)
	    return 0;
	ccmp_init_blocks(&key, wh, PN, data_len, b0, aad, a, b);
	memcpy(mic, m+len-AIRPDCAP_CCMP_TRAILER, AIRPDCAP_CCMP_TRAILER);
	XOR_BLOCK(mic, b, AIRPDCAP_CCMP_TRAILER);

	i = 1;
	pos = (UINT8 *)m + z + AIRPDCAP_CCMP_HEADER;
	space = len - (z + AIRPDCAP_CCMP_HEADER);

	if (space > data_len)
		space = (UINT)data_len;
	while (space >= AES_BLOCK_LEN) {
		CCMP_DECRYPT(i, b, b0, pos, a, AES_BLOCK_LEN);
		pos += AES_BLOCK_LEN, space -= AES_BLOCK_LEN;
		data_len -= AES_BLOCK_LEN;
		i++;
	}

	if (space != 0)         /* short last block */
		CCMP_DECRYPT(i, b, b0, pos, a, space);

	/*	MIC Key ?= MIC																				*/
	if (memcmp(mic, a, AIRPDCAP_CCMP_TRAILER) == 0) {
		return 0;
	}

	/* TODO replay check	(IEEE 802.11i-2004, pg. 62)			*/
	/* TODO PN must be incremental (IEEE 802.11i-2004, pg. 62)		*/

	return 1;
}
コード例 #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 {