/** * peerkey_verify_eapol_key_mic - Verify PeerKey MIC * @sm: Pointer to WPA state machine data from wpa_sm_init() * @peerkey: Pointer to the PeerKey data for the peer * @key: Pointer to the EAPOL-Key frame header * @ver: Version bits from EAPOL-Key Key Info * @buf: Pointer to the beginning of EAPOL-Key frame * @len: Length of the EAPOL-Key frame * Returns: 0 on success, -1 on failure */ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, struct wpa_peerkey *peerkey, struct wpa_eapol_key *key, u16 ver, const u8 *buf, size_t len) { u8 mic[16]; int ok = 0; if (peerkey->initiator && !peerkey->stk_set) { wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", sm->own_addr, peerkey->addr, peerkey->inonce, key->key_nonce, (u8 *) &peerkey->stk, sizeof(peerkey->stk), peerkey->use_sha256); peerkey->stk_set = 1; } os_memcpy(mic, key->key_mic, 16); if (peerkey->tstk_set) { os_memset(key->key_mic, 0, 16); wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len, key->key_mic); if (os_memcmp(mic, key->key_mic, 16) != 0) { wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " "when using TSTK - ignoring TSTK"); } else { ok = 1; peerkey->tstk_set = 0; peerkey->stk_set = 1; os_memcpy(&peerkey->stk, &peerkey->tstk, sizeof(peerkey->stk)); } } if (!ok && peerkey->stk_set) { os_memset(key->key_mic, 0, 16); wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len, key->key_mic); if (os_memcmp(mic, key->key_mic, 16) != 0) { wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " "- dropping packet"); return -1; } ok = 1; } if (!ok) { wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC " "- dropping packet"); return -1; } os_memcpy(peerkey->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); peerkey->replay_counter_set = 1; return 0; }
static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, struct wpa_eapol_key *key, u16 ver, const u8 *buf, size_t len) { u8 mic[16]; int ok = 0; os_memcpy(mic, key->key_mic, 16); if (sm->tptk_set) { os_memset(key->key_mic, 0, 16); wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len, key->key_mic); if (os_memcmp(mic, key->key_mic, 16) != 0) { lwip_log("WPA: Invalid EAPOL-Key MIC when using TPTK - ignoring TPTK\n"); } else { ok = 1; sm->tptk_set = 0; sm->ptk_set = 1; os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk)); } } if (!ok && sm->ptk_set) { os_memset(key->key_mic, 0, 16); wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len, key->key_mic); if (os_memcmp(mic, key->key_mic, 16) != 0) { lwip_log("WPA: Invalid EAPOL-Key MIC - dropping packet\n"); return -1; } ok = 1; } if (!ok) { lwip_log("WPA: Could not verify EAPOL-Key MIC - dropping packet\n"); return -1; } os_memcpy(sm->rx_replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); sm->rx_replay_counter_set = 1; return 0; }
static int check_mic(const u8 *kck, int ver, const u8 *data, size_t len) { u8 *buf; int ret = -1; struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; u8 rx_mic[16]; buf = os_malloc(len); if (buf == NULL) return -1; os_memcpy(buf, data, len); hdr = (struct ieee802_1x_hdr *) buf; key = (struct wpa_eapol_key *) (hdr + 1); os_memcpy(rx_mic, key->key_mic, 16); os_memset(key->key_mic, 0, 16); if (wpa_eapol_key_mic(kck, ver, buf, len, key->key_mic) == 0 && os_memcmp(rx_mic, key->key_mic, 16) == 0) ret = 0; os_free(buf); return ret; }
/** * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message * @sm: Pointer to WPA state machine data from wpa_sm_init() * @kck: Key Confirmation Key (KCK, part of PTK) * @ver: Version field from Key Info * @dest: Destination address for the frame * @proto: Ethertype (usually ETH_P_EAPOL) * @msg: EAPOL-Key message * @msg_len: Length of message * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written */ void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, int ver, const u8 *dest, u16 proto, u8 *msg, size_t msg_len, u8 *key_mic) { if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) { /* * Association event was not yet received; try to fetch * BSSID from the driver. */ if (wpa_sm_get_bssid(sm, sm->bssid) < 0) { wpa_printf(MSG_DEBUG, "WPA: Failed to read BSSID for " "EAPOL-Key destination address"); } else { dest = sm->bssid; wpa_printf(MSG_DEBUG, "WPA: Use BSSID (" MACSTR ") as the destination for EAPOL-Key", MAC2STR(dest)); } } if (key_mic && wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic)) { wpa_printf(MSG_ERROR, "WPA: Failed to generate EAPOL-Key " "version %d MIC", ver); goto out; } wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len); wpa_sm_ether_send(sm, dest, proto, msg, msg_len); eapol_sm_notify_tx_eapol_key(sm->eapol); out: os_free(msg); }
static void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, int ver, const u8 *dest, u16 proto, u8 *msg, size_t msg_len, u8 *key_mic) { #if 0 if (os_memcmp(dest, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 && os_memcmp(sm->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) { /* * Association event was not yet received; try to fetch * BSSID from the driver. */ if (wpa_sm_get_bssid(sm, sm->bssid) < 0) { lwip_log("WPA: Failed to read BSSID for EAPOL-Key destination address\n"); } else { dest = sm->bssid; lwip_log("WPA: Use BSSID (" MACSTR ") as the destination for EAPOL-Key\n", MAC2STR(dest)); } } #endif //generate MIC. if (key_mic) { wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic); } wpa_ether_send(dest, proto, msg, msg_len); os_free(msg); }