Developer notes for wpa_supplicant
==================================

The design goal for wpa_supplicant was to use hardware, driver, and OS
independent, portable C code for all WPA functionality. All
hardware/driver specific functionality is in separate files that
implement a well-defined driver API.

The goal of this file and the comments in the header files is to give
enough information for other developers to be able to port the example
code. If any information is missing, feel free to contact Jouni Malinen
<jkmaline@cc.hut.fi> for more information. Contributions as patch files
are also very welcome at the same address.

Structure of the source code
----------------------------

Program initialization, main control loop and event handling is
implemented in wpa_supplicant.c. WPA state machines and 4-Way/Group
Key Handshake processing in in wpa.c. IEEE 802.1X/EAPOL processing and
state machines are in eapol_sm.c. EAP state machine is in eap.c. EAP
methods for the internal EAP peer are in eap_*.c.  Parser for the
configuration file is implemented in config.c.

Driver interface API is defined in driver.h and all hardware/driver
dependent functionality is implemented in driver_*.c (see below).


Generic helper functions
------------------------

wpa_supplicant uses generic helper functions some of which are shared
with with hostapd. The following C files are currently used:

eloop.[ch]
	event loop (select() loop with registerable timeouts, socket read
	callbacks, and signal callbacks)

common.[ch]
	common helper functions

defs.h
	definitions shared by multiple files

l2_packet.[ch]
	Layer 2 (link) access wrapper (includes native Linux implementation
	and wrappers for libdnet/libpcap)

pcsc_funcs.[ch]
	Wrapper for PC/SC lite SIM and smart card readers


Cryptographic functions
-----------------------

md5.c
	MD5 (replaced with openssl/crypto if TLS support is included)
	HMAC-MD5 (keyed checksum for message authenticity validation)

rc4.c
	RC4 (broadcast/default key encryption)

sha1.c
	SHA-1 (replaced with openssl/crypto if TLS support is included)
	HMAC-SHA-1 (keyed checksum for message authenticity validation)
	PRF-SHA-1 (pseudorandom (key/nonce generation) function)
	PBKDF2-SHA-1 (ASCII passphrase to shared secret)
	T-PRF (for EAP-FAST)
	TLS-PRF (RFC 2246)

aes_wrap.[ch], aes.c
	AES
	AES Key Wrap Algorithm with 128-bit KEK, RFC3394 (broadcast/default
	key encryption)
	One-Key CBC MAC (OMAC1) hash with AES-128
	AES-128 CTR mode encryption
	AES-128 EAX mode encryption/decryption
	AES-128 CBC

crypto.[ch]
	Wrapper functions for libcrypto (MD4 and DES)

ms_funcs.[ch]
	Helper functions for MSCHAPV2 and LEAP

tls.h
	Definition of TLS library wrapper

tls_none.c
	Dummy implementation of TLS library wrapper for cases where TLS
	functionality is not included.

tls_openssl.c
	TLS library wrapper for openssl


Configuration
-------------

config_ssid.h
	Definition of per network configuration items

config.h
	Definition of the wpa_supplicant configuration

config.c
	Configuration file parser


Control interface
-----------------

wpa_supplicant has a control interface that can be used to get status
information and manage operations from external programs. An example,
command line interface, wpa_cli, for this interface is included in the
wpa_supplicant distribution.

ctrl_iface.[ch]
	wpa_supplicant-side of the control interface

wpa_ctrl.[ch]
	Library functions for external programs to provide access to the
	wpa_supplicant control interface

wpa_cli.c
	Example program for using wpa_supplicant control interface


EAP peer
--------

eap.[ch]
	EAP state machine

eap_defs.h
	Common EAP definitions

eap_i.h
	Internal definitions for EAP state machine and EAP methods

eap_sim_common.[ch]
	Common code for EAP-SIM and EAP-AKA

eap_tls_common.[ch]
	Common code for EAP-PEAP, EAP-TTLS, and EAP-FAST

eap_tlv.[ch]
	EAP-TLV code for EAP-PEAP and EAP-FAST

eap_{aka,fast,gtc,leap,md5,mschapv2,otp,peap,psk,sim,tls,ttls}.c
	EAP method implementations


EAPOL supplicant
----------------

eapol_sm.[ch]
	EAPOL supplicant state machine and IEEE 802.1X processing


Windows port
------------

ndis_events.cpp
	External program for receiving NdisMIndicateStatus() events and
	delivering them to wpa_supplicant in more easier to use form

win_if_list.c
	External program for listing current network interface


Test programs
-------------

radius_client.[ch]
	RADIUS authentication client implementation for eapol_test

eapol_test.c
	Standalone EAP testing tool with integrated RADIUS authentication
	client

preauth_test.c
	Standalone RSN pre-authentication tool


wpa_supplicant.c
----------------

main()
- parse command line
- call config file parser
- initialize Supplicant data structures
- call functions to initialize WPA support in the driver
- initialize event loop
- cleanup when exiting

wpa_supplicant_dot1x_receive()
- receive master session key update from Xsupplicant (optional)

wpa_supplicant_get_beacon_ie()

wpa_supplicant_deauthenticate()

wpa_supplicant_disassociate()

wpa_supplicant_scan()

wpa_supplicant_reconfig()
- SIGHUP signal processing

wpa_supplicant_terminate()
- SIGINT and SIGTERM processing

wpa_supplicant_reload_configuration()

wpa_supplicant_event()
- receive driver events (through driver wrapper functions)
  * wpa_supplicant_scan_results(): process scan result event, BSS selection
  * wpa_supplicant_associnfo(): process association information event

wpa_supplicant_associate()
- control association (select cipher and key management suites, initiate
  association)

wpa_supplicant_req_auth_timeout()

wpa_supplicant_cancel_auth_timeout()

wpa_supplicant_req_scan()

wpa_supplicant_cancel_scan()

wpa_supplicant_notify_eapol_done()

wpa_eapol_send()
- send EAPOL frames

wpa_eapol_send_preauth()
- send RSN preauthentication frames

wpa_msg()
- event/debug function


wpa_supplicant.h
----------------

- driver event definition
- common function definition (e.g., wpa_msg)


wpa_supplicant_i.h
------------------
- internal definitions for wpa_supplicant; must not be included into
  common code, EAP methods, driver interface implementations


wpa.[ch]
--------
- WPA supplicant state machine and 4-Way/Group Key Handshake processing
- PMKSA cache and RSN pre-authentication

pmksa_cache_free()

pmksa_cache_get()

pmksa_cache_list()

pmksa_candidate_free()

wpa_parse_wpa_ie()
- WPA/RSN IE parsing

wpa_gen_wpa_ei()
- WPA/RSN IE generation

wpa_supplicant_get_ssid()

wpa_supplicant_key_request()
- trigger function to start key requests

wpa_sm_rx_eapol()
- WPA processing for received EAPOL-Key frames
  * wpa_supplicant_process_1_of_4() (message 1 of 4-Way Handshake)
  * wpa_supplicant_process_3_of_4() (message 3 of 4-Way Handshake)
  * wpa_supplicant_process_1_of_2() (message 1 of Group Key Handshake)

wpa_supplicant_rx_eapol()
- l2_packet RX callback for EAPOL frames; sends the frames to WPA and EAPOL
  state machines for further processing

wpa_get_mib()

rsn_preauth_receive()
- l2_packet RX callback for preauthentication frames

rsn_preauth_eapol_cb()
- callback function to be called when EAPOL authentication has been completed
  (either successfully or unsuccessfully) for RSN pre-authentication

rsn_preauth_init()
rsn_preauth_deinit()

pmksa_candidate_add()
- add a BSSID to PMKSA candidate list

rsn_preauth_scan_results()
- update RSN pre-authentication candidate list based on scan results


Driver wrapper implementation (driver.h, drivers.c)
---------------------------------------------------

All hardware and driver dependent functionality is implemented in as a
separate C file(s) implementing defined wrapper functions. Other parts
of the wpa_supplicant are designed to be hardware, driver, and operating
system independent.

Driver wrappers need to implement whatever calls are used in the
target operating system/driver for controlling wireless LAN
devices. As an example, in case of Linux, these are mostly some glue
code and ioctl() calls and netlink message parsing for Linux Wireless
Extensions. Since all features required for WPA are not yet included
in Wireless Extensions, some driver specific code is used in the
example implementation for Host AP driver. These driver dependent parts
are to be replaced with generic code once the needed changes are
included in the Wireless Extensions. After that, all Linux drivers, at
least in theory, could use the same driver wrapper code.

A driver wrapper needs to implement some or all of the functions
defined in driver.h (see that file for detailed documentation of the
functions). Hardware independent parts of wpa_supplicant will call
these functions to control the driver/wlan card. In addition, support
for driver events is required. The event callback function,
wpa_supplicant_event(), and its parameters are documented in
wpa_supplicant.h. In addition, pointer to the 'struct wpa_driver_ops'
needs to be registered in drivers.c file.

When porting to other operating systems, driver wrapper should be
modified to use the native interface of the target OS. It is possible
that some extra requirements for the interface between the driver
wrapper and generic wpa_supplicant code are discovered during porting
to a new operating system. These will be addresses on case by case
basic by modifying the interface and updating the other driver
wrappers for this. The goal is to avoid changing this interface
without very good reasons in order to limit the number of changes
needed to other wrappers and hardware independent parts of
wpa_supplicant.

Generic Linux Wireless Extensions functions are implemented in
driver_wext.c. All Linux driver wrappers can use these when the kernel
driver supports the generic ioctl()s and wireless events. Driver
specific functions are implemented in separate C files, e.g.,
driver_hostap.c. These files need to define struct wpa_driver_ops
entry that will be used in wpa_supplicant.c when calling driver
functions. These entries need to be added to the lists in
wpa_supplicant_set_driver() and usage() functions in wpa_supplicant.c.

In general, it is likely to be useful to first take a look at couple
of the driver interfaces before starting on implementing a new
one. driver_hostap.c and driver_wext.c include a complete
implementation for Linux drivers that use wpa_supplicant-based control
of WPA IE and roaming. driver_ndis.c (with help from driver_ndis_.c)
is an example of a complete interface for Windows NDIS interface for
drivers that generate WPA IE themselves and decide when to roam. These
example implementations include full support for all security modes.


Driver requirements for WPA
---------------------------

WPA introduces new requirements for the device driver. At least some
of these need to be implemented in order to provide enough support for
wpa_supplicant.

TKIP/CCMP

WPA requires that the pairwise cipher suite (encryption algorithm for
unicast data packets) is TKIP or CCMP. These are new encryption
protocols and thus, the driver will need to be modified to support
them. Depending on the used wlan hardware, some parts of these may be
implemented by the hardware/firmware.

Specification for both TKIP and CCMP is available from IEEE (IEEE
802.11i draft version 3.0). Fully functional, hardware independent
implementation of both encryption protocols is also available in Host
AP driver (driver/modules/hostap_{tkip,ccmp}.c).

The driver will also need to provide configuration mechanism to allow
user space programs to configure TKIP and CCMP. Current Linux Wireless
Extensions (v16) does not yet support these algorithms or
individual/non-default keys. Host AP driver has an example of private
ioctl()s for this. Eventually, this should be replaced with modified
Linux Wireless Extensions.

Roaming control and scanning support

wpa_supplicant controls AP selections based on the information
received from Beacon and/or Probe Response frames. This means that the
driver should support external control for scan process. In case of
Linux, use of new Wireless Extensions scan support (i.e., 'iwlist
wlan0 scan') is recommended. The current driver wrapper (driver_wext.c)
uses this for scan results.

Scan results must also include WPA information element. This is not
yet defined in Linux Wireless Extensions and Host AP driver uses a
custom event to provide the full WPA IE (including element id and
length) as a hex string that is included in the scan results.
Eventually, this should be defined as a Wireless Extensions ioctl
that can be used both with scan results and with configuration of WPA IE
for association request (and Beacon/Probe Response in case of an
AP/IBSS).

wpa_supplicant needs to also be able to request the driver to
associate with a specific BSS. Current Host AP driver and matching
driver_hostap.c wrapper uses following sequence for this
request. Similar/identical mechanism should be usable also with other
drivers.

- set WPA IE for AssocReq with private ioctl
- set SSID with SIOCSIWESSID
- set channel/frequency with SIOCSIWFREQ
- set BSSID with SIOCSIWAP
  (this last ioctl will trigger the driver to request association)

WPA IE generation

wpa_supplicant selects which cipher suites and key management suites
are used. Based on this information, it generates a WPA IE. This is
provided to the driver interface in the associate call. This does not
match with Windows NDIS drivers which generate the WPA IE
themselves.

wpa_supplicant allows Windows NDIS-like behavior by providing the
selected cipher and key management suites in the associate call. If
the driver generates its own WPA IE and that differs from the one
generated by wpa_supplicant, the driver has to inform wpa_supplicant
about the used WPA IE (i.e., the one it used in (Re)Associate
Request). This notification is done using EVENT_ASSOCINFO event (see
wpa_supplicant.h).

Driver events

wpa_supplicant needs to receive event callbacks when certain events
occur (association, disassociation, Michael MIC failure, scan results
available, PMKSA caching candidate). These events and the callback
details are defined in wpa_supplicant.h.

On Linux, association and disassociation can use existing Wireless
Extensions event that is reporting new AP with SIOCGIWAP
event. Similarly, completion of scan can be reported with SIOCGIWSCAN
event.

Michael MIC failure event is not yet included in Wireless Extensions,
so this needs a custom event. Host AP driver uses custom event with
following contents: MLME-MICHAELMICFAILURE.indication(keyid=#
broadcast/unicast addr=addr2). This is the recommended format until
the event is added to Linux Wireless Extensions.
