Table of Contents

Some wireless implementation details

Network association

Before an 802.11 device can be used, it must become associated with a network by exchanging a series of management frames with the Access Point. In some cases there is additional security handshaking required after association. gPXE's 802.11 layer handles this transparently by always having the association task running if association has not yet succeeded, and using the link-up bit in the wrapping net_device to indicate association status. Commands such as DHCP or autoboot will therefore block on association success, and time out if an underlying error condition rather than a transient failure is responsible for association not working.

After association has succeeded, reassociation will be attempted upon a change in the SSID setting. It is not necessary to reassociate when the encryption key is changed, because association can only succeed with an invalid key on an open-system WEP network, and rekeying does not require reassociation in that case. If the user specified the encryption key erroneously at first, association will fail and be retried indefinitely, and will succeed soon after the correct key is provided.

Association is handled in a separate gPXE process, which runs through a series of states in predetermined order:

Encrypted networks support

The gPXE 802.11 layer includes abstract support for encrypted wireless networks, as well as implementations of that support for WEP- and WPA-protected networks. We introduce two abstractions: a security handshaker and a wireless cryptosystem.

Security handshakers

A security handshaker is responsible for everything that must occur before encrypted packets can be sent and received: deriving a master encryption key from the user's specified net0/key, securely authenticating to the Access Point by some specified means, possibly deriving more keys from the master key and using them instead of or in addition to the master key, and specifying encryption keys and a cryptosystem to use them for packet-level security. The currently implemented security handshakers are “trivial”, WPA-Personal (PSK / pre-shared key), and WPA-Enterprise (802.1X / EAP). The trivial handshaker, used for WEP, just does some sanity checks on the user-specified key and then installs it directly without a further exchange with the AP. The WPA handshakers interface with a common WPA core, supplying it with a pairwise master key derived either from the user's passphrase (for Personal) or the EAP Master Session Key (for Enterprise).

It is not possible to manually specify the security handshaker to be used for a network; it is autodetected by _sec80211_detect() in net/80211/sec80211.c. gPXE's linker tables are searched for a handshaker of the requisite type, a new structure is allocated with space for the requested amount of private data, and dev→handshaker is set to point at it. The dev→handshaker pointer remains valid from the time the handshaker's init() method is called to the time its stop() method is called.

Additional security handshakers are declared using gPXE's linker table mechanism, by defining a structure of type net80211_handshaker tagged with the __net80211_handshaker attribute, containing the following fields:

When a security handshaker has finished negotiating whatever handshaking is necessary, it will usually need to finish its job by setting up the 802.11 device to use some sort of cryptography on all future data packets. This is accomplished by the function:

#include <gpxe/sec80211.h>
int sec80211_install ( struct net80211_crypto **which,
                       enum net80211_crypto_alg crypt,
                       const void *key, int len, const void *rsc );

Install the 802.11 cryptosystem of type crypt for packets handled by which, which is &dev→crypto for unicast RX and all TX packets, or &dev→gcrypto for broadcast RX packets. The encryption key is len bytes and is pointed to by key. If applicable to the cryptosystem in question, the initial receive sequence counter is pointed to by rsc with a cryptosystem-dependent length; NULL can be passed for an RSC of zero.

The currently defined values for crypt are:

Cryptosystems

Supporting a new crypto method, if one ever comes into use, is a matter of updating net/80211/sec80211.c to recognize it (if it uses WPA handshaking, edit the rsn_cipher_map array at the beginning of that file) and adding a cryptosystem to implement it.

Similarly to security handshakers, cryptosystems are provided using a linker table: define a struct net80211_crypto tagged with __net80211_crypto and including some or all of the following fields:

The cryptosystem implementations are expected to be “pure”; that is, they should not need to access any properties of the 802.11 device that are not contained in the frame headers themselves. To enforce this expectation, they are not provided with a net80211_device pointer.

The implementation of sec80211_install simply searches for a cryptosystem implementing the requested algorithm, allocates storage for it in dev→crypto or dev→gcrypto, and calls its init() method with the key and RSC it is given.

More 802.11 details

The 802.11 code is extensively documented using Doxygen comments, on both API and internal functions. To further understand what it's doing, I recommend the following sources:

Hints for reading the 802.11 spec

The standard is divided into 19 “clauses” (roughly chapters) and 16 “annexes” (appendices). You certainly do not need to read all of them. The useful ones are

If you run into something you can't figure out, email me (username oremanj located at the domain rwcr in the TLD .net) and I'll be happy to try and clarify.