wpa::eapol
The EAPOL-Key frame: the wire format of the 4-way handshake.
Every message of the handshake is an EAPOL-Key frame — an 802.1X header
followed by a fixed 95-byte key body and a variable key-data trailer. This
module reads a received frame, identifies which of the four messages it is
from its key_info flags, verifies its MIC, and builds the station’s two
replies. It is pure byte-handling over crypto; the state
machine that decides what to do lives in [super::handshake].
Layout and flag values are transcribed from esp-idf’s wpa_common.h /
wpa.c — the reference the blobs on the other end were built against —
rather than from a reading of the standard, for the same reason
[super]’s crypto matches its vectors: interoperation is the whole point.
Structs
Section titled “Structs”EapolKey
Section titled “EapolKey”struct EapolKey<'a> { /* private fields */ }A read-only view over a received EAPOL-Key frame.
Borrows the buffer; the accessors read fields by offset. Construct with
parse, which bounds-checks the length once so the
accessors need not.
Message
Section titled “Message”enum Message { One, Three, Other,}Which of the four handshake messages a frame is.
Implements: Clone, Copy, Debug, Eq, PartialEq, StructuralPartialEq
Functions
Section titled “Functions”build_reply
Section titled “build_reply”fn build_reply(version: u16, kck: &[u8], reply_info: u16, replay_counter: &[u8; 8], nonce: &[u8; 32], key_data: &[u8], out: &mut [u8]) -> Option<usize>Build the station’s reply (message 2 or 4) into out, returning its length.
reply_info is the key_info for the reply — the caller sets the flags per
the message. nonce is the SNonce for message 2, ignored (send zeros) for
message 4. key_data is the station’s RSN IE for message 2, empty for
message 4. The MIC is computed last, over the finished frame.
compute_mic
Section titled “compute_mic”fn compute_mic(version: u16, kck: &[u8], frame: &[u8]) -> Option<[u8; 16]>Compute the MIC over frame under kck for descriptor version.
The MIC field in the frame is treated as zero for the computation, whatever it currently holds — so this works both to verify a received frame (its MIC is present) and to fill in an outgoing one (its MIC is still zero).
flag_version_sha1
Section titled “flag_version_sha1”fn flag_version_sha1() -> u16Descriptor version 2 — HMAC-SHA1 MIC, AES-key-wrapped key data. The version WPA2-CCMP uses, and the only one the handshake here handles.
info_is_secure
Section titled “info_is_secure”fn info_is_secure(key_info: u16) -> boolWhether a frame’s key_info has the SECURE bit — carried into message 4.
reply_info_msg2
Section titled “reply_info_msg2”fn reply_info_msg2(version: u16) -> u16The key_info for message 2: version, pairwise, MIC.
reply_info_msg4
Section titled “reply_info_msg4”fn reply_info_msg4(version: u16, msg3_secure: bool) -> u16The key_info for message 4: version, pairwise, MIC, and SECURE carried
over from message 3.
Constants
Section titled “Constants”EAPOL_HDR_LEN
Section titled “EAPOL_HDR_LEN”const EAPOL_HDR_LEN: usize;The 802.1X header: version, type, body length. Precedes the key body.
EAPOL_TYPE_KEY
Section titled “EAPOL_TYPE_KEY”const EAPOL_TYPE_KEY: u8;EAPOL packet type 3 — an EAPOL-Key frame.
KEY_BODY_LEN
Section titled “KEY_BODY_LEN”const KEY_BODY_LEN: usize;The fixed part of the EAPOL-Key body, before the variable key data.
KEY_DESC_RSN
Section titled “KEY_DESC_RSN”const KEY_DESC_RSN: u8;Key descriptor type 2 — RSN (WPA2).
MIC_LEN
Section titled “MIC_LEN”const MIC_LEN: usize;The MIC is 16 bytes for every descriptor version handled here.
MIN_FRAME_LEN
Section titled “MIN_FRAME_LEN”const MIN_FRAME_LEN: usize;The smallest a valid EAPOL-Key frame can be: header + fixed body.
NONCE_LEN
Section titled “NONCE_LEN”const NONCE_LEN: usize;A nonce is 32 bytes.