unsigned int ieee80211_get_hdrlen(FAR const struct ieee80211_frame *wh) { unsigned int size = sizeof(*wh); /* NB: does not work with control frames */ DEBUGASSERT(ieee80211_has_seq(wh)); if (ieee80211_has_addr4(wh)) { size += IEEE80211_ADDR_LEN; /* i_addr4 */ } if (ieee80211_has_qos(wh)) { size += sizeof(uint16_t); /* i_qos */ } if (ieee80211_has_htc(wh)) { size += sizeof(uint32_t); /* i_ht */ } return size; }
/*- * Counter with CBC-MAC (CCM) - see RFC3610. * CCMP uses the following CCM parameters: M = 8, L = 2 */ static void ieee80211_ccmp_phase1(rijndael_ctx *ctx, const struct ieee80211_frame *wh, u_int64_t pn, int lm, u_int8_t b[16], u_int8_t a[16], u_int8_t s0[16]) { u_int8_t auth[32], nonce[13]; u_int8_t *aad; u_int8_t tid = 0; int la, i; /* construct AAD (additional authenticated data) */ aad = &auth[2]; /* skip l(a), will be filled later */ *aad = wh->i_fc[0]; /* 11w: conditionnally mask subtype field */ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) *aad &= ~IEEE80211_FC0_SUBTYPE_MASK; aad++; /* protected bit is already set in wh */ *aad = wh->i_fc[1]; *aad &= ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT | IEEE80211_FC1_MORE_DATA); /* 11n: conditionnally mask order bit */ if (ieee80211_has_htc(wh)) *aad &= ~IEEE80211_FC1_ORDER; aad++; IEEE80211_ADDR_COPY(aad, wh->i_addr1); aad += IEEE80211_ADDR_LEN; IEEE80211_ADDR_COPY(aad, wh->i_addr2); aad += IEEE80211_ADDR_LEN; IEEE80211_ADDR_COPY(aad, wh->i_addr3); aad += IEEE80211_ADDR_LEN; *aad++ = wh->i_seq[0] & ~0xf0; *aad++ = 0; if (ieee80211_has_addr4(wh)) { IEEE80211_ADDR_COPY(aad, ((const struct ieee80211_frame_addr4 *)wh)->i_addr4); aad += IEEE80211_ADDR_LEN; } if (ieee80211_has_qos(wh)) { *aad++ = tid = ieee80211_get_qos(wh) & IEEE80211_QOS_TID; *aad++ = 0; } /* construct CCM nonce */ nonce[ 0] = tid; if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT) nonce[0] |= 1 << 4; /* 11w: set management bit */ IEEE80211_ADDR_COPY(&nonce[1], wh->i_addr2); nonce[ 7] = pn >> 40; /* PN5 */ nonce[ 8] = pn >> 32; /* PN4 */ nonce[ 9] = pn >> 24; /* PN3 */ nonce[10] = pn >> 16; /* PN2 */ nonce[11] = pn >> 8; /* PN1 */ nonce[12] = pn; /* PN0 */ /* add 2 authentication blocks (including l(a) and padded AAD) */ la = aad - &auth[2]; /* fill l(a) */ auth[0] = la >> 8; auth[1] = la & 0xff; memset(aad, 0, 30 - la); /* pad AAD with zeros */ /* construct first block B_0 */ b[ 0] = 89; /* Flags = 64*Adata + 8*((M-2)/2) + (L-1) */ memcpy(&b[1], nonce, 13); b[14] = lm >> 8; b[15] = lm & 0xff; rijndael_encrypt(ctx, b, b); for (i = 0; i < 16; i++) b[i] ^= auth[i]; rijndael_encrypt(ctx, b, b); for (i = 0; i < 16; i++) b[i] ^= auth[16 + i]; rijndael_encrypt(ctx, b, b); /* construct S_0 */ a[ 0] = 1; /* Flags = L' = (L-1) */ memcpy(&a[1], nonce, 13); a[14] = a[15] = 0; rijndael_encrypt(ctx, a, s0); }