关于Wi-Fi的加密认证过程,可以参考如下链接,今天我们来理解如何生成GTK。
WLAN数据加密机制_tls加密wifi-CSDN博客
1 GTK
GTK(Group Temporal Key)是由AP通过GMK生成,长度为128位,并在四次握手的第三步中通过加密的方式发送给STA。具体步骤如下:
- GTK生成:AP生成一个新的GTK。这个GTK是AP自己生成的随机密钥,用于加密多播和广播通信。
- Note:所以连接到同一个AP的STA都拥有相同GTK。
- GTK分发:在四次握手的第三步,AP将GTK加密后发送给STA。加密使用的是PTK中的KEK(Key Encryption Key)部分。
- Note:关于KEK请参考链接:WLAN 4-Way Handshake如何生成PTK?-CSDN博客
1.1 GTK生成的具体步骤
Wi-Fi使用伪随机函数(PRF)生成GTK。常用的PRF实现基于HMAC-SHA1或HMAC-SHA256,如下图所示:
- 在WPA和WPA2中,通常使用HMAC-SHA1。
- 在WPA3中,使用更强的HMAC-SHA256。
Note:
- 当前GMK由随机数代替;
- 为了防止GTK泄露,AP应定期生成新的GTK并分发给所有STA。
如上图所示,GTK密钥生成的层级,我们这里重点讲解下生成算法,我们可以看到生成的算法是PRF-Length,其中Length的计算方法如下所示:
- Length =TK_bits.
- 其中TK_bits的值参考下图:
1.2 GTK的传递过程
四次握手的具体步骤包括以下内容:
- 消息1:AP生成ANonce,并发送给STA。
- 消息2:STA生成SNonce,并发送给AP。STA和AP都计算出PTK。
- 消息3:
- AP生成GTK。
- AP使用PTK中的KEK加密GTK。
- AP将加密的GTK和一个MIC(Message Integrity Code)发送给STA,以保证消息的完整性和保密性。
- 消息4:STA接收到加密的GTK后,使用PTK中的KEK解密,得到GTK,并发送确认消息给AP。
1.3 GTK更新和重新分发
AP定期生成新的GTK,并通过以下过程重新分发:
- 生成新的GTK:使用上述算法和步骤生成新的GTK。
- 通知STA:通过新的EAPOL-Key消息通知所有连接的STA。
- 加密传输:使用PTK中的KEK加密新的GTK,并发送给STA。
- 确认:STA接收到新的GTK后,解密并确认接收。
1.4 hostapd code
static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,struct wpa_group *group)
{if (group->first_sta_seen)return;/** System has run bit further than at the time hostapd was started* potentially very early during boot up. This provides better chances* of collecting more randomness on embedded systems. Re-initialize the* GMK and Counter here to improve their strength if there was not* enough entropy available immediately after system startup.*/wpa_printf(MSG_DEBUG,"WPA: Re-initialize GMK/Counter on first station");if (random_pool_ready() != 1) {wpa_printf(MSG_INFO,"WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake");group->reject_4way_hs_for_entropy = true;} else {group->first_sta_seen = true;group->reject_4way_hs_for_entropy = false;}if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||wpa_gtk_update(wpa_auth, group) < 0 ||wpa_group_config_group_keys(wpa_auth, group) < 0) {wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");group->first_sta_seen = false;group->reject_4way_hs_for_entropy = true;}
}static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,struct wpa_group *group)
{struct wpa_auth_config *conf = &wpa_auth->conf;int ret = 0;size_t len;os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);inc_byte_array(group->Counter, WPA_NONCE_LEN);if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",wpa_auth->addr, group->GNonce,group->GTK[group->GN - 1], group->GTK_len) < 0)ret = -1;wpa_hexdump_key(MSG_DEBUG, "GTK",group->GTK[group->GN - 1], group->GTK_len);if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {len = wpa_cipher_key_len(conf->group_mgmt_cipher);os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);inc_byte_array(group->Counter, WPA_NONCE_LEN);if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",wpa_auth->addr, group->GNonce,group->IGTK[group->GN_igtk - 4], len) < 0)ret = -1;wpa_hexdump_key(MSG_DEBUG, "IGTK",group->IGTK[group->GN_igtk - 4], len);}if (!wpa_auth->non_tx_beacon_prot &&conf->ieee80211w == NO_MGMT_FRAME_PROTECTION)return ret;if (!conf->beacon_prot)return ret;if (wpa_auth->conf.tx_bss_auth) {group = wpa_auth->conf.tx_bss_auth->group;if (group->bigtk_set)return ret;wpa_printf(MSG_DEBUG, "Set up BIGTK for TX BSS");}len = wpa_cipher_key_len(conf->group_mgmt_cipher);os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);inc_byte_array(group->Counter, WPA_NONCE_LEN);if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",wpa_auth->addr, group->GNonce,group->BIGTK[group->GN_bigtk - 6], len) < 0)return -1;group->bigtk_set = true;wpa_hexdump_key(MSG_DEBUG, "BIGTK",group->BIGTK[group->GN_bigtk - 6], len);return ret;
}