path: root/wpa_supplicant
diff options
authorMike Siedzik <msiedzik@extremenetworks.com>2018-02-20 19:28:39 (GMT)
committerJouni Malinen <j@w1.fi>2018-12-26 14:42:25 (GMT)
commit2fc0675683aba203c89c507f2aeca8ae51446043 (patch)
tree2a72c18dcb5cdd39956fb8a40141614b82be7529 /wpa_supplicant
parentd9a0a72229cd71553be69dd76e7bf4560f2be05e (diff)
mka: Fix lowest acceptable Packet Number (LPN) calculation and use
The purpose of the Lowest Acceptable PN (lpn) parameters in the MACsec SAK Use parameter set is to enforce delay protection. Per IEEE Std 802.1X-2010, Clause 9, "Each SecY uses MKA to communicate the lowest PN used for transmission with the SAK within the last two seconds, allowing receivers to bound transmission delays." When encoding the SAK Use parameter set the KaY should set llpn and olpn to the lowest PN transmitted by the latest SAK and oldest SAK (if active) within the last two seconds. Because MKPDUs are transmitted every 2 seconds (MKA_HELLO_TIME), the solution implemented here calculates lpn based on the txsc->next_pn read during the previous MKPDU transmit. Upon receiving and decoding a SAK Use parameter set with delay protection enabled, the KaY will update the SecY's lpn if the delay protect lpn is greater than the SecY's current lpn (which is a product of last PN received and replay protection and window size). Signed-off-by: Michael Siedzik <msiedzik@extremenetworks.com>
Diffstat (limited to 'wpa_supplicant')
2 files changed, 15 insertions, 0 deletions
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 86c891a..4a9f472 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -804,6 +804,14 @@ static inline int wpa_drv_set_transmit_next_pn(struct wpa_supplicant *wpa_s,
return wpa_s->driver->set_transmit_next_pn(wpa_s->drv_priv, sa);
+static inline int wpa_drv_set_receive_lowest_pn(struct wpa_supplicant *wpa_s,
+ struct receive_sa *sa)
+ if (!wpa_s->driver->set_receive_lowest_pn)
+ return -1;
+ return wpa_s->driver->set_receive_lowest_pn(wpa_s->drv_priv, sa);
static inline int
wpa_drv_create_receive_sc(struct wpa_supplicant *wpa_s, struct receive_sc *sc,
unsigned int conf_offset, int validation)
diff --git a/wpa_supplicant/wpas_kay.c b/wpa_supplicant/wpas_kay.c
index c662bbb..99599da 100644
--- a/wpa_supplicant/wpas_kay.c
+++ b/wpa_supplicant/wpas_kay.c
@@ -92,6 +92,12 @@ static int wpas_set_transmit_next_pn(void *wpa_s, struct transmit_sa *sa)
+static int wpas_set_receive_lowest_pn(void *wpa_s, struct receive_sa *sa)
+ return wpa_drv_set_receive_lowest_pn(wpa_s, sa);
static unsigned int conf_offset_val(enum confidentiality_offset co)
switch (co) {
@@ -219,6 +225,7 @@ int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
kay_ctx->get_receive_lowest_pn = wpas_get_receive_lowest_pn;
kay_ctx->get_transmit_next_pn = wpas_get_transmit_next_pn;
kay_ctx->set_transmit_next_pn = wpas_set_transmit_next_pn;
+ kay_ctx->set_receive_lowest_pn = wpas_set_receive_lowest_pn;
kay_ctx->create_receive_sc = wpas_create_receive_sc;
kay_ctx->delete_receive_sc = wpas_delete_receive_sc;
kay_ctx->create_receive_sa = wpas_create_receive_sa;