一文轻松让你理解WLAN MIC的机制

1. References

1.1 引用笔记

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帧。在这种情况下,使用下表中相应的行。

        • 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,那么此位保留。

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;
}
  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值