From 3f3e60e41512bc6561e1baba33855149d361271f Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Fri, 6 Jan 2017 02:51:18 -0500 Subject: [PATCH] eapol: Check the MSK size supplied by EAP Despite RFC3748 mandating MSKs to be at least 256 bits some EAP methods return shorter MSKs. Since we call handshake_failed when the MSK is too short, EAP methods have to be careful with their calls to set_key_material because it may result in a call to the method's .remove method. EAP-TLS and EAP-TTLS can't handle that currently and would be difficult to adapt because of the TLS internals but they always set msk_len to 64 so handshake_failed will not be called. --- src/eapol.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/eapol.c b/src/eapol.c index c347e4a9..fcaaff54 100644 --- a/src/eapol.c +++ b/src/eapol.c @@ -1419,6 +1419,8 @@ static void eapol_eap_results_cb(const uint8_t *msk_data, size_t msk_len, void *user_data) { struct eapol_sm *sm = user_data; + ssize_t pmk_len; + const uint8_t *pmk_data; l_debug("EAP key material received"); @@ -1443,10 +1445,26 @@ static void eapol_eap_results_cb(const uint8_t *msk_data, size_t msk_len, * 802.1X authentication), i.e., XXKey = L(MSK, 256, 256)." */ - if (sm->handshake->akm_suite == IE_RSN_AKM_SUITE_FT_OVER_8021X) - handshake_state_set_pmk(sm->handshake, msk_data + 32); - else - handshake_state_set_pmk(sm->handshake, msk_data); + if (sm->handshake->akm_suite == IE_RSN_AKM_SUITE_FT_OVER_8021X) { + pmk_len = (ssize_t) msk_len - 32; + pmk_data = msk_data + 32; + } else { + pmk_len = msk_len; + pmk_data = msk_data; + } + + if (pmk_len < 32) + goto msk_short; + + handshake_state_set_pmk(sm->handshake, pmk_data); + + return; + +msk_short: + l_error("EAP method's MSK too short for AKM suite %u", + sm->handshake->akm_suite); + + handshake_failed(sm, MPDU_REASON_CODE_IEEE8021X_FAILED); } static void eapol_eap_event_cb(unsigned int event,