PMK Hierarchy - IEEE 802.11-2020 §12.6 | Source: IEEE 802.11i / 802.11r9 rows#
| Key Name | Length (bits) | Derived From | Algorithm | Used For | Scope | Derivation Detail | Notes |
|---|---|---|---|---|---|---|---|
| PMK | 256 | MSK (EAP) or PSK (PBKDF2) | PBKDF2-SHA1 (PSK) or MSK truncation (EAP) | Seed for PTK derivation | Per-BSS association | PSK: PMK = PBKDF2-HMAC-SHA1(passphrase, SSID, 4096, 256) EAP: PMK = MSK[0:256] (first 256 bits of MSK) | Never transmitted. Stored in PMKSA cache. Lifetime = dot11RSNAConfigPMKLifetime (default 43200 s) |
| PMK-R0 | 256 | PMK (802.11r) | KDF-256(XXKey, 'FT-R0', SSIDlen||SSID||MDID||R0KHlen||R0KH-ID||S0KH-ID) - XXKey = PSK, or MSK[32:64] for 802.1X | FT key hierarchy root | R0KH domain (same key holder) | R0KH-ID + S0KH-ID define the domain. Derived at initial association with FT BSS. | Stored at R0KH (often the WLC). Not sent to AP - only PMK-R1 is pushed. |
| PMK-R1 | 256 | PMK-R0 (802.11r) | KDF-256(PMK-R0, 'FT-R1', R1KH-ID||S1KH-ID) | PTK derivation during FT roam | Per-AP (R1KH) | R0KH pushes PMK-R1 to target R1KH over R0KH-R1KH interface (typically 802.11r over-DS or over-Air). | Allows target AP to derive PTK without STA re-running full EAP. |
| PTK | 384 (CCMP-128) or 704 (WPA3-Ent 192-bit) | PMK (or PMK-R1 for FT) | PRF-384/KDF-SHA256 (CCMP-128) or KDF-SHA384-704 (192-bit suite) | Encrypts unicast data & EAPOL | Per-STA per-session | PTK = PRF-X(PMK, 'Pairwise key expansion', Min(AA,SPA)||Max(AA,SPA)||Min(ANonce,SNonce)||Max(ANonce,SNonce)) Input concatenation is sorted to ensure both sides compute identical value. | Split: KCK|KEK|TK. Fresh ANonce+SNonce ensures session uniqueness = perfect forward secrecy (WPA3). |
| KCK | 128 or 192 | PTK[0:128] or [0:192] | - | MIC in EAPOL-Key messages | Per-session | KCK = PTK bits [0:KCK_len]. Used with HMAC-SHA1-128 (WPA2 AKM 2), AES-128-CMAC (WPA3-SAE AKM 8), HMAC-SHA384 (192-bit AKM 12). | If KCK is wrong (PSK mismatch), MIC in EAPOL msg 2 fails → AP sends msg 1 again → eventual timeout. |
| KEK | 128 or 256 | PTK[KCK_len : KCK_len+KEK_len] | - | Encrypts GTK/IGTK in EAPOL msg 3 | Per-session | KEK = PTK bits [128:256] (CCMP) or [192:448] (GCMP-256). Encrypts key data in EAPOL-Key message 3 using AES-KeyWrap (RFC 3394). | AES KeyWrap ensures GTK/IGTK are delivered confidentially. Without KEK encryption, GTK could be sniffed. |
| TK | 128 or 256 | PTK[KCK+KEK : end] | - | CCMP or GCMP data encryption | Per-STA session | TK = PTK[256:384] for CCMP-128. TK = PTK[448:704] for GCMP-256. Used directly as AES key in CCMP/GCMP counter mode. | TK change requires new 4-way handshake or GTK rekey. TK reuse with nonce reuse is the KRACK vulnerability. |
| GTK | 128 or 256 | GMK (Group Master Key) | PRF-X(GMK, 'Group key expansion', AA || GKNonce) | Encrypts broadcast/multicast | Per-BSS (all STAs share) | AP generates GMK randomly. GTK derived from GMK. Delivered to STA in EAPOL msg 3 encrypted with KEK. | GTK rekeying: triggered on STA departure (prevent eavesdropping) or dot11RSNAConfigGroupRekeyTime expiry. |
| IGTK | 128 or 256 | BIPN GMK | PRF-X(GMK, 'IGTK key expansion', ...) | Protects broadcast/multicast mgmt frames (PMF/802.11w) | Per-BSS | IGTK delivered alongside GTK in EAPOL msg 3. Used with BIP-CMAC-128 or BIP-GMAC-256. | Required for WPA3 (PMF mandatory). Prevents forged broadcast Deauth/Disassoc attacks. |
4-Way Handshake Message Sequence - IEEE 802.11-2020 §12.7.6.34 rows#
| Msg | Direction | EAPOL-Key Info Fields | Key Data Content | Purpose | MIC Present? | Timer / Retry | Common Failure Mode |
|---|---|---|---|---|---|---|---|
| Msg 1 (EAPOL-Key) | AP → STA | Key Info: Pairwise=1, ACK=1, MIC=0, Secure=0, Install=0 Key Length: 16 or 32 Replay Counter: N (starts at 1) Key Nonce: ANonce (32B random) Key MIC: 000...0 (zero - no MIC yet) | Empty (no key data) | AP sends ANonce. STA now has PMK+ANonce and generates SNonce → computes PTK | No MIC (initial message) | Retransmit after dot11RSNAConfigPairwiseUpdateCount (4) if no Msg 2 | STA never responds: PSK mismatch (STA has wrong PMK so ignores MIC failure in Msg 3), or STA crashed |
| Msg 2 (EAPOL-Key) | STA → AP | Key Info: Pairwise=1, MIC=1, Secure=0, Install=0, ACK=0 Replay Counter: N (must match Msg 1) Key Nonce: SNonce (32B random) Key MIC: HMAC(KCK, EAPOL body) | RSN IE (STA capabilities - AP validates match to Assoc Req RSN IE) | STA sends SNonce + MIC. AP can now compute PTK and verify MIC. | YES - first authenticated message | If AP MIC check fails → retransmit Msg 1 (AP thinks Msg 1 was lost) | MIC failure in Msg 2 = PSK/PMK mismatch (most common WPA2 failure). dot11AuthenticateFailedCount++ |
| Msg 3 (EAPOL-Key) | AP → STA | Key Info: Pairwise=1, Install=1, ACK=1, MIC=1, Secure=1, Encrypted=1 Replay Counter: N+1 Key Nonce: ANonce (repeated) Key MIC: HMAC(KCK, EAPOL body) | GTK encrypted with KEK (AES-KeyWrap RFC 3394) IGTK (if PMF/802.11w enabled) RSN IE (AP's RSN IE - STA validates match) | AP installs TK on its side. Sends GTK+IGTK to STA encrypted. STA validates AP's RSN IE matches beacon. | YES | KRACK vulnerability: if Msg 4 lost, AP retransmits Msg 3 with same nonce → STA re-installs TK → nonce reset → keystream reuse | RSN IE mismatch between Msg 3 and Beacon → STA tears down connection (man-in-middle indicator) |
| Msg 4 (EAPOL-Key) | STA → AP | Key Info: Pairwise=1, MIC=1, Secure=1, ACK=0 Replay Counter: N+1 (matches Msg 3) Key Nonce: 000...0 (zeroes) Key MIC: HMAC(KCK, EAPOL body) | Empty | STA confirms receipt of Msg 3. After sending Msg 4, STA installs TK and can send encrypted data. | YES | AP installs TK after receiving valid Msg 4 | KRACK patch: AP must NOT retransmit Msg 3 after receiving Msg 4. Check: dot11RSNAStatsTKIPLocalMICFailures |
GTK 2-Way Handshake (Group Rekey) - IEEE 802.11-2020 §12.7.72 rows#
| Msg | Direction | Key Info Flags | Key Data | Purpose | Timer | Notes | - |
|---|---|---|---|---|---|---|---|
| Msg 1 | AP → All STAs | Key Info: Group=1, ACK=1, MIC=1, Secure=1, Encrypted=1 | New GTK encrypted with each STA's KEK (individual unicast to each STA) | Distribute new GTK after a STA departs (revocation) or rekey timer expires | dot11RSNAConfigGroupRekeyTime (default 3600 s) dot11RSNAConfigGroupUpdateCount | Each STA receives individualized unicast msg 1 (same new GTK but encrypted with their unique KEK). Broadcast would expose GTK. | - |
| Msg 2 | STA → AP | Key Info: Group=1, MIC=1, Secure=1, ACK=0 | Empty | STA confirms new GTK received and installed | - | STA starts using new GTK for receiving multicast/broadcast immediately. Transmit GTK update completes cycle. | - |
EAPOL-Key Frame Structure - IEEE 802.11-2020 §12.7.2 | IEEE 802.1X-2010 §11.3 | Every field explained21 rows#
| Field | Offset (bytes) | Length (bytes) | Msg 1 Value | Msg 2 Value | Msg 3 Value | Msg 4 Value | Engineering Purpose |
|---|---|---|---|---|---|---|---|
| Protocol Version | 0 | 1 | 0x01 (802.1X-2001) or 0x03 (802.1X-2010) | Same | Same | Same | Identifies EAPOL version. Some devices fail if version ≠ expected - source of interop bugs. |
| Packet Type | 1 | 1 | 0x03 (EAPOL-Key) | 0x03 | 0x03 | 0x03 | Must be 3 for all 4-way handshake messages. Type 0=EAP, 1=EAPOL-Start, 2=EAPOL-Logoff. |
| Packet Body Length | 2 | 2 | Variable | Variable | Variable | Variable | Total length of EAPOL-Key body that follows. Used by receiver to allocate buffer. |
| Descriptor Type | 4 | 1 | 0x02 (RSN/WPA2) or 0xFE (WPA legacy) | Same | Same | Same | Identifies key descriptor format. Must be 0x02 for WPA2/WPA3. WPA1 uses 0xFE. |
| Key Information | 5 | 2 | Bit flags (see below) | Bit flags | Bit flags | Bit flags | 16-bit bitmap: [KeyDescVersion(2:0)][KeyType(3)][Reserved(5:4)][Install(6)][KeyACK(7)][KeyMIC(8)][Secure(9)][Error(10)][Request(11)][Encrypted(12)][SMK(13)][Reserved(15:14)] |
| Key Descriptor Version | 5 | bits 2:0 | 1=HMAC-MD5+RC4 (WPA) 2=HMAC-SHA1-128+AES (WPA2 CCMP) 3=AES-128-CMAC+AES (WPA2 GCMP) | Same | Same | Same | Determines MIC and encryption algorithms used in handshake. Version 3 used for GCMP cipher suites. |
| Key Type | 5 | bit 3 | 1 (Pairwise) | 1 (Pairwise) | 1 (Pairwise) | 1 (Pairwise) | 0=Group key (GTK), 1=Pairwise key (PTK). All 4-way messages use 1. GTK handshake uses 0. |
| Install | 5 | bit 6 | 0 (don't install) | 0 | 1 (install TK now) | 0 | Set to 1 in Msg 3 to tell STA to install the TK derived from PTK. STA installs TK after Msg 4 sent. |
| Key ACK | 5 | bit 7 | 1 (expects response) | 0 | 1 | 0 | Set by sender expecting a response. AP sets in Msg 1 and Msg 3. STA does not set in Msg 2 or 4. |
| Key MIC | 5 | bit 8 | 0 (no MIC yet) | 1 (MIC present) | 1 | 1 | Indicates MIC field is valid. First MIC appears in Msg 2 (proves STA has correct PMK). Zero in Msg 1 = MIC field all zeros. |
| Secure | 5 | bit 9 | 0 | 0 | 1 (GTK installed) | 1 | Set when sender has installed GTK. AP sets in Msg 3 (GTK is in key data). STA echoes in Msg 4. |
| Encrypted Key Data | 5 | bit 12 | 0 | 0 | 1 (GTK encrypted) | 0 | Set when key data field is AES-KeyWrap encrypted. Must be 1 in Msg 3 (GTK/IGTK wrapped with KEK). |
| Key Length | 7 | 2 | 16 or 32 | 0 | 16 or 32 | 0 | Length of PTK's TK in bytes (16=CCMP-128, 32=GCMP-256). Zero in Msg 2 and 4 (STA does not send key length). |
| Replay Counter | 9 | 8 | N (AP starts at 1, increments per exchange) | N (echoes Msg 1) | N+1 (new counter) | N+1 (echoes Msg 3) | 8-byte monotonically increasing counter. Prevents replay attacks. STA must reject Msg 1 with counter ≤ previously seen value. |
| Key Nonce | 17 | 32 | ANonce (AP random 32B) | SNonce (STA random 32B) | ANonce (repeated from Msg 1) | 000...0 (all zeros) | Random nonce for PTK derivation. Both ANonce and SNonce feed into PTK = PRF(PMK, nonces, MACs). Zeros in Msg 4 signal completion. |
| EAPOL-Key IV | 49 | 16 | 000...0 | 000...0 | 000...0 (or random for WPA1) | 000...0 | Initialization vector. All zeros in WPA2/WPA3 (AES-KeyWrap does not use IV). Used in legacy WPA1 RC4 encryption. |
| Key RSC | 65 | 8 | 000...0 | 000...0 | GTK RSC (receive sequence counter) | 000...0 | Receive Sequence Counter for GTK. AP sets in Msg 3 to tell STA the last GTK packet number sent (prevents replay with new GTK). |
| Reserved | 73 | 8 | 000...0 | 000...0 | 000...0 | 000...0 | Reserved field. Must be zero. Some implementations check this - non-zero → frame reject. |
| Key MIC | 81 | 16 or 24 or 32 | 000...0 (no MIC in Msg 1) | HMAC-SHA1-128(KCK, EAPOL body) | HMAC(KCK, EAPOL body) | HMAC(KCK, EAPOL body) | Message Integrity Code over entire EAPOL-Key frame (with MIC field zeroed for computation). Length: 16B (CCMP), 24B (GCMP-256). KRACK: MIC field zeroed before verify. |
| Key Data Length | 97 | 2 | 0 | len(RSN IE) | len(GTK+IGTK wrapped) | 0 | Length of Key Data field that follows. Zero = no key data. Msg 2 carries RSN IE (~22B). Msg 3 carries AES-KeyWrapped GTK (~40B) + IGTK (~32B). |
| Key Data | 99 | Variable | (empty) | RSN IE: tag=0x30, len, group cipher, pairwise count, pairwise suite, AKM count, AKM suite, RSN caps, PMKID count, PMKID | AES-KeyWrap(KEK, GTK KDE + IGTK KDE + RSN IE) | (empty) | Key Data contains Key Data Encapsulations (KDEs) or IEs. GTK KDE: type=0xDD, OUI=00:0F:AC, type=1, KeyID+Tx flag, GTK value. IGTK KDE: type=0xDD, OUI=00:0F:AC, type=9, KeyID, IPN, IGTK value. |