1. References
- 4-Way Hand shake , Keys generation and MIC Verification-WPA2 – Praneeth's Blog (4-Way Hand shake , Keys generation and MIC Verification-WPA2)
1.1 引用笔记
- WLAN数据加密机制_tls加密wifi-CSDN博客
- WLAN 4-Way Handshake如何生成PTK?-CSDN博客
- WLAN 4-Way Handshake如何生成GTK?_wifi gtk-CSDN博客
- WLAN的WPA3安全技术_wpa3 pwe-CSDN博客
- GTK是如何加密WLAN组播和广播数据的?-CSDN博客
- PTK是如何加密WLAN单播数据帧的?-CSDN博客
- WLAN_Features_Training-CSDN博客
- 一招教你获得你想要的图表-CSDN博客
- WLAN Hostapd配置参数详解 - CN_hostapd n40 配置-CSDN博客
- WLAN Transmit Beamforming (TxBF)_etxbfencond enables sending of sounding and beamfo-CSDN博客
2. 引入话题
众所周知,在Wi-Fi的使用过程中,为了确保数据的安全性,我们会对其数据进行加密。为了达到加密的目的,就需要加密密钥,对于Wi-Fi来说,最主要的两个加密密钥是PTK(成对临时密钥)和GTK(组临时密钥),其PTK用于加密单播数据,而GTK用于加密广播和多播数据。其PTK和GTK的生成,就不得不提Wi-Fi的四步握手了。本篇我们不过多的介绍四步握手,而是对四步握手的EAPOL帧中的MIC字段进行一个详细的理解。
3. MIC详解
消息完整性码(Message Integrity Code,MIC)是用于确保数据完整性和真实性的安全机制。在Wi-Fi通信中,MIC的主要作用是检测和防止数据在传输过程中被篡改。
如上是Wi-Fi的4-way handshake过程,我们可以清晰的看到M2/M3/M4都包含了MIC,以确保数据的准确性。接下来我们详细的讲解下MIC的生成过程。
3.1 EAPOL帧
EAPOL(Extensible Authentication Protocol over LAN)是用于在局域网(LAN)中传输EAP消息的协议。EAPOL帧在IEEE 802.1X认证过程中起着关键作用,特别是在Wi-Fi网络中用于WPA、WPA2和WPA3的四次握手协议。EAPOL帧的格式具体如下所示:
EAPOL帧的字段详解如下所示:
- Descriptor Type: 这个字段的值定义在IEEE 802.1X-2010中,具体如下所示:
- Key Information: 这个字段描述了密钥的特性,具体如下所示:
-
- Key Descriptor Version (bits 0–2): 应在所有的EAPOL-Key帧上设置为0,表明EAPOL-Key帧是根据下表所述的AKM构建和处理的,除以下情况外:
- 当协商的AKM是00-0F-AC:1或00-0F-AC:2且“the pairwise cipher”密码是TKIP或“Use group cipher suite”时,此值应该为1,且应用于所有发送到STA的EAPOL-Key帧。在这种情况下,使用下表中的“Deprecated”行。
- 当协商的AKM是00-0F-AC:1或00-0F-AC:2且“the pairwise or the group cipher”密码是除TKIP之外的增强数据加密机制时,此值应该为2, 且应用于所有发送到STA的EAPOL-Key帧。在这种情况下,使用下表中相应的行。
- 当协商的AKM是00-0F-AC:3、00-0F-AC:4、00-0F-AC:5或00-0F-AC:6时,此值应该为3,且应用于所有发送到STA的EAPOL-Key帧。在这种情况下,使用下表中相应的行。
- Key Descriptor Version (bits 0–2): 应在所有的EAPOL-Key帧上设置为0,表明EAPOL-Key帧是根据下表所述的AKM构建和处理的,除以下情况外:
-
-
-
- AKM的组合如下图所示:
-
-
-
- Key Type (bit 3): 指定此EAPOL-Key帧是否属于生成PTK的四步握手的一部分。
- 0(Group)表示该消息不属于PTK派生的一部分。
- 1(Pairwise)表示该消息属于PTK派生的一部分。
- Reserved (bits 4–5).
- Install (bit 6).
- 如果"Key Type"的值为1,则Install如下:
- 1表示IEEE 802.1X组件应将从该消息派生的临时密钥配置到其IEEE 802.11 MAC中。
- 0表示IEEE 802.1X组件不应将临时密钥配置到IEEE 802.11 MAC中。
- 如果"Key Type"的值为0,那么此位保留。
- 如果"Key Type"的值为1,则Install如下:
- Key Type (bit 3): 指定此EAPOL-Key帧是否属于生成PTK的四步握手的一部分。
3.2 MIC的生成
MIC的计算方式如下所示,根据AKM的不同,MIC的生成算法和长度也不一样。
3.2.1 hostapd/wpa_supplicant code
/**
* wpa_eapol_key_mic - Calculate EAPOL-Key MIC
* @key: EAPOL-Key Key Confirmation Key (KCK)
* @key_len: KCK length in octets
* @akmp: WPA_KEY_MGMT_* used in key derivation
* @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
* @buf: Pointer to the beginning of the EAPOL header (version field)
* @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
* @mic: Pointer to the buffer to which the EAPOL-Key MIC is written
* Returns: 0 on success, -1 on failure
*
* Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has
* to be cleared (all zeroes) when calling this function.
*
* Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the
* description of the Key MIC calculation. It includes packet data from the
* beginning of the EAPOL-Key header, not EAPOL header. This incorrect change
* happened during final editing of the standard and the correct behavior is
* defined in the last draft (IEEE 802.11i/D10).
*/
int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
const u8 *buf, size_t len, u8 *mic)
{
u8 hash[SHA512_MAC_LEN];
if (key_len == 0) {
wpa_printf(MSG_DEBUG,
"WPA: KCK not set - cannot calculate MIC");
return -1;
}
switch (ver) {
#ifndef CONFIG_FIPS
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-MD5");
return hmac_md5(key, key_len, buf, len, mic);
#endif /* CONFIG_FIPS */
case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-SHA1");
if (hmac_sha1(key, key_len, buf, len, hash))
return -1;
os_memcpy(mic, hash, MD5_MAC_LEN);
break;
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using AES-CMAC");
return omac1_aes_128(key, buf, len, mic);
case WPA_KEY_INFO_TYPE_AKM_DEFINED:
switch (akmp) {
#ifdef CONFIG_SAE
case WPA_KEY_MGMT_SAE:
case WPA_KEY_MGMT_FT_SAE:
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - SAE)");
return omac1_aes_128(key, buf, len, mic);
case WPA_KEY_MGMT_SAE_EXT_KEY:
case WPA_KEY_MGMT_FT_SAE_EXT_KEY:
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - SAE-EXT-KEY)",
(unsigned int) key_len * 8 * 2);
if (key_len == 128 / 8) {
if (hmac_sha256(key, key_len, buf, len, hash))
return -1;
#ifdef CONFIG_SHA384
} else if (key_len == 192 / 8) {
if (hmac_sha384(key, key_len, buf, len, hash))
return -1;
#endif /* CONFIG_SHA384 */
#ifdef CONFIG_SHA512
} else if (key_len == 256 / 8) {
if (hmac_sha512(key, key_len, buf, len, hash))
return -1;
#endif /* CONFIG_SHA512 */
} else {
wpa_printf(MSG_INFO,
"SAE: Unsupported KCK length: %u",
(unsigned int) key_len);
return -1;
}
os_memcpy(mic, hash, key_len);
break;
#endif /* CONFIG_SAE */
#ifdef CONFIG_HS20
case WPA_KEY_MGMT_OSEN:
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - OSEN)");
return omac1_aes_128(key, buf, len, mic);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_SUITEB
case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC using HMAC-SHA256 (AKM-defined - Suite B)");
if (hmac_sha256(key, key_len, buf, len, hash))
return -1;
os_memcpy(mic, hash, MD5_MAC_LEN);
break;
#endif /* CONFIG_SUITEB */
#ifdef CONFIG_SUITEB192
case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - Suite B 192-bit)");
if (hmac_sha384(key, key_len, buf, len, hash))
return -1;
os_memcpy(mic, hash, 24);
break;
#endif /* CONFIG_SUITEB192 */
#ifdef CONFIG_OWE
case WPA_KEY_MGMT_OWE:
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - OWE)",
(unsigned int) key_len * 8 * 2);
if (key_len == 128 / 8) {
if (hmac_sha256(key, key_len, buf, len, hash))
return -1;
} else if (key_len == 192 / 8) {
if (hmac_sha384(key, key_len, buf, len, hash))
return -1;
} else if (key_len == 256 / 8) {
if (hmac_sha512(key, key_len, buf, len, hash))
return -1;
} else {
wpa_printf(MSG_INFO,
"OWE: Unsupported KCK length: %u",
(unsigned int) key_len);
return -1;
}
os_memcpy(mic, hash, key_len);
break;
#endif /* CONFIG_OWE */
#ifdef CONFIG_DPP
case WPA_KEY_MGMT_DPP:
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - DPP)",
(unsigned int) key_len * 8 * 2);
if (key_len == 128 / 8) {
if (hmac_sha256(key, key_len, buf, len, hash))
return -1;
} else if (key_len == 192 / 8) {
if (hmac_sha384(key, key_len, buf, len, hash))
return -1;
} else if (key_len == 256 / 8) {
if (hmac_sha512(key, key_len, buf, len, hash))
return -1;
} else {
wpa_printf(MSG_INFO,
"DPP: Unsupported KCK length: %u",
(unsigned int) key_len);
return -1;
}
os_memcpy(mic, hash, key_len);
break;
#endif /* CONFIG_DPP */
#ifdef CONFIG_SHA384
case WPA_KEY_MGMT_IEEE8021X_SHA384:
#ifdef CONFIG_IEEE80211R
case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
#endif /* CONFIG_IEEE80211R */
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - 802.1X SHA384)");
if (hmac_sha384(key, key_len, buf, len, hash))
return -1;
os_memcpy(mic, hash, 24);
break;
#endif /* CONFIG_SHA384 */
default:
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC algorithm not known (AKM-defined - akmp=0x%x)",
akmp);
return -1;
}
break;
default:
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC algorithm not known (ver=%d)",
ver);
return -1;
}
return 0;
}