}
-static u8 * try_ptk(int pairwise_cipher, struct wpa_ptk *ptk,
- const struct ieee80211_hdr *hdr,
+static u8 * try_ptk(struct wlantest *wt, int pairwise_cipher,
+ struct wpa_ptk *ptk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len)
{
u8 *decrypted;
data, data_len, decrypted_len);
} else if ((pairwise_cipher == WPA_CIPHER_TKIP ||
pairwise_cipher == 0) && tk_len == 32) {
+ enum michael_mic_result mic_res;
+
decrypted = tkip_decrypt(ptk->tk, hdr, data, data_len,
- decrypted_len);
+ decrypted_len, &mic_res);
+ if (decrypted && mic_res == MICHAEL_MIC_INCORRECT)
+ add_note(wt, MSG_INFO, "Invalid Michael MIC");
+ else if (decrypted && mic_res == MICHAEL_MIC_NOT_VERIFIED)
+ add_note(wt, MSG_DEBUG, "Michael MIC not verified");
}
return decrypted;
wpa_debug_level = MSG_WARNING;
dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
- decrypted = try_ptk(pairwise_cipher, &ptk->ptk, hdr,
+ decrypted = try_ptk(wt, pairwise_cipher, &ptk->ptk, hdr,
data, data_len, decrypted_len);
if (decrypted) {
wpa_debug_level = prev_level;
}
skip_replay_det:
- if (bss->group_cipher == WPA_CIPHER_TKIP)
+ if (bss->group_cipher == WPA_CIPHER_TKIP) {
+ enum michael_mic_result mic_res;
+
decrypted = tkip_decrypt(bss->gtk[keyid], hdr, data, len,
- &dlen);
- else if (bss->group_cipher == WPA_CIPHER_WEP40)
+ &dlen, &mic_res);
+ if (decrypted && mic_res == MICHAEL_MIC_INCORRECT)
+ add_note(wt, MSG_INFO, "Invalid Michael MIC");
+ else if (decrypted && mic_res == MICHAEL_MIC_NOT_VERIFIED)
+ add_note(wt, MSG_DEBUG, "Michael MIC not verified");
+ } else if (bss->group_cipher == WPA_CIPHER_WEP40) {
decrypted = wep_decrypt(wt, hdr, data, len, &dlen);
- else if (bss->group_cipher == WPA_CIPHER_CCMP)
+ } else if (bss->group_cipher == WPA_CIPHER_CCMP) {
decrypted = ccmp_decrypt(bss->gtk[keyid], hdr, data, len,
&dlen);
- else if (bss->group_cipher == WPA_CIPHER_CCMP_256)
+ } else if (bss->group_cipher == WPA_CIPHER_CCMP_256) {
decrypted = ccmp_256_decrypt(bss->gtk[keyid], hdr, data, len,
&dlen);
- else if (bss->group_cipher == WPA_CIPHER_GCMP ||
- bss->group_cipher == WPA_CIPHER_GCMP_256)
+ } else if (bss->group_cipher == WPA_CIPHER_GCMP ||
+ bss->group_cipher == WPA_CIPHER_GCMP_256) {
decrypted = gcmp_decrypt(bss->gtk[keyid], bss->gtk_len[keyid],
hdr, data, len, &dlen);
+ }
if (decrypted) {
char gtk[65];
write_decrypted_note(wt, decrypted, tk, 16, keyid);
}
} else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) {
- decrypted = tkip_decrypt(sta->ptk.tk, hdr, data, len, &dlen);
+ enum michael_mic_result mic_res;
+
+ decrypted = tkip_decrypt(sta->ptk.tk, hdr, data, len, &dlen,
+ &mic_res);
+ if (decrypted && mic_res == MICHAEL_MIC_INCORRECT)
+ add_note(wt, MSG_INFO, "Invalid Michael MIC");
+ else if (decrypted && mic_res == MICHAEL_MIC_NOT_VERIFIED)
+ add_note(wt, MSG_DEBUG, "Michael MIC not verified");
write_decrypted_note(wt, decrypted, sta->ptk.tk, 32, keyid);
} else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) {
decrypted = wep_decrypt(wt, hdr, data, len, &dlen);
os_memset(&zero_ptk, 0, sizeof(zero_ptk));
zero_ptk.tk_len = wpa_cipher_key_len(sta->pairwise_cipher);
wpa_debug_level = MSG_ERROR;
- decrypted = try_ptk(sta->pairwise_cipher, &zero_ptk, hdr,
+ decrypted = try_ptk(wt, sta->pairwise_cipher, &zero_ptk, hdr,
data, len, &dlen);
wpa_debug_level = old_debug_level;
if (decrypted) {
u8 * tkip_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
- const u8 *data, size_t data_len, size_t *decrypted_len)
+ const u8 *data, size_t data_len, size_t *decrypted_len,
+ enum michael_mic_result *mic_res)
{
u16 iv16;
u32 iv32;
u8 michael_hdr[16];
u8 mic[8];
u16 fc = le_to_host16(hdr->frame_control);
+ u16 sc = le_to_host16(hdr->seq_ctrl);
if (data_len < 8 + 4)
return NULL;
plain_len -= 4;
/* TODO: MSDU reassembly */
+ if ((fc & WLAN_FC_MOREFRAG) || WLAN_GET_SEQ_FRAG(sc) > 0) {
+ /* For now, return the decrypted fragment and do not check the
+ * Michael MIC value in the last fragment */
+ *decrypted_len = plain_len;
+ if (mic_res) {
+ *mic_res = MICHAEL_MIC_NOT_VERIFIED;
+ return plain;
+ }
+ }
if (plain_len < 8) {
wpa_printf(MSG_INFO, "TKIP: Not enough room for Michael MIC "
wpa_hexdump(MSG_DEBUG, "TKIP: Calculated MIC", mic, 8);
wpa_hexdump(MSG_DEBUG, "TKIP: Received MIC",
plain + plain_len - 8, 8);
+ if (mic_res) {
+ *decrypted_len = plain_len - 8;
+ *mic_res = MICHAEL_MIC_INCORRECT;
+ return plain;
+ }
os_free(plain);
return NULL;
+ } else if (mic_res) {
+ *mic_res = MICHAEL_MIC_OK;
}
*decrypted_len = plain_len - 8;
u8 * ccmp_256_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
u8 *qos, u8 *pn, int keyid, size_t *encrypted_len);
+enum michael_mic_result {
+ MICHAEL_MIC_OK,
+ MICHAEL_MIC_INCORRECT,
+ MICHAEL_MIC_NOT_VERIFIED
+};
u8 * tkip_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
- const u8 *data, size_t data_len, size_t *decrypted_len);
+ const u8 *data, size_t data_len, size_t *decrypted_len,
+ enum michael_mic_result *mic_res);
u8 * tkip_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos,
u8 *pn, int keyid, size_t *encrypted_len);
void tkip_get_pn(u8 *pn, const u8 *data);