/* Compute Message Integrity Code (MIC) over EAPOL message */ bool BCMROMFN(wpa_make_mic)(eapol_header_t *eapol, uint key_desc, uint8 *mic_key, uchar *mic) { int mic_length; /* length of eapol pkt from the version field on */ mic_length = 4 + ntoh16_ua((uint8 *)&eapol->length); /* Create the MIC for the pkt */ switch (key_desc) { case WPA_KEY_DESC_V1: hmac_md5(&eapol->version, mic_length, mic_key, EAPOL_WPA_KEY_MIC_LEN, mic); break; case WPA_KEY_DESC_V2: hmac_sha1(&eapol->version, mic_length, mic_key, EAPOL_WPA_KEY_MIC_LEN, mic); break; case WPA_KEY_DESC_V3: aes_cmac_calc(&eapol->version, mic_length, mic_key, EAPOL_WPA_KEY_MIC_LEN, mic); break; default: return FALSE; } return TRUE; }
/* calculates BIP; mic must be at least AES_BLOCK_SZ */ static void bip_calc(const struct dot11_header *hdr, const uint8 *data, int data_len, const uint8 *key, uint8 * mic) { uint len; uint8* micdata; uint16 fc; memset(mic, 0 , AES_BLOCK_SZ); micdata = malloc(2 + 3 * ETHER_ADDR_LEN + data_len); if (!micdata) return; fc = htol16(ltoh16(hdr->fc) & ~(FC_RETRY | FC_PM | FC_MOREDATA)); len = 0; memcpy((char *)&micdata[len], (uint8 *)&fc, 2); len += 2; memcpy(&micdata[len], (uint8 *)&hdr->a1, ETHER_ADDR_LEN); len += ETHER_ADDR_LEN; memcpy(&micdata[len], (uint8 *)&hdr->a2, ETHER_ADDR_LEN); len += ETHER_ADDR_LEN; memcpy(&micdata[len], (uint8 *)&hdr->a3, ETHER_ADDR_LEN); len += ETHER_ADDR_LEN; memcpy(&micdata[len], data, data_len); len += data_len; aes_cmac_calc(micdata, len, key, BIP_KEY_SIZE, mic); free(micdata); }