From cd7af67aace5e581f0ee7cce68e65e778ab5434f Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Thu, 19 Oct 2017 14:40:15 -0500 Subject: [PATCH] eapol: Tighten up GTK/IGTK KDE validation GTK KDE was being checked for being a minimum of 6 bytes. Not quite sure why since the minimum GTK key length is 16 bytes for CCMP. Similarly make sure that the maximum length is not more than 32, which is currently the largest key size (TKIP) --- src/crypto.h | 6 ++++++ src/eapol.c | 23 +++++++++++------------ src/handshake.c | 40 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/crypto.h b/src/crypto.h index f170b257..e19c4665 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -43,6 +43,12 @@ enum crypto_akm { CRYPTO_AKM_FT_OVER_SAE_SHA256 = 0x000fac09, }; +/* Min & Max reported by crypto_cipher_key_len when ignoring WEP */ +#define CRYPTO_MIN_GTK_LEN 16 +#define CRYPTO_MAX_GTK_LEN 32 +#define CRYPTO_MIN_IGTK_LEN 16 +#define CRYPTO_MAX_IGTK_LEN 32 + struct crypto_ptk { uint8_t kck[16]; uint8_t kek[16]; diff --git a/src/eapol.c b/src/eapol.c index 415cc3fc..6c5a9deb 100644 --- a/src/eapol.c +++ b/src/eapol.c @@ -1231,7 +1231,7 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm, gtk = handshake_util_find_gtk_kde(decrypted_key_data, decrypted_key_data_size, >k_len); - if (!gtk || gtk_len < 8) { + if (!gtk) { handshake_failed(sm, MMPDU_REASON_CODE_UNSPECIFIED); return; } @@ -1248,7 +1248,7 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm, igtk = handshake_util_find_igtk_kde(decrypted_key_data, decrypted_key_data_size, &igtk_len); - if (!igtk || igtk_len < 8) { + if (!igtk) { handshake_failed(sm, MMPDU_REASON_CODE_UNSPECIFIED); return; } @@ -1336,29 +1336,28 @@ static void eapol_handle_gtk_1_of_2(struct eapol_sm *sm, gtk = handshake_util_find_gtk_kde(decrypted_key_data, decrypted_key_data_size, >k_len); - - if (!gtk || gtk_len < 8) + if (!gtk) return; + + gtk_key_index = util_bit_field(gtk[0], 0, 2); + gtk += 2; + gtk_len -= 2; } else { gtk = decrypted_key_data; gtk_len = decrypted_key_data_size; - if (!gtk || gtk_len < 6) + if (!gtk || gtk_len < CRYPTO_MIN_GTK_LEN || + gtk_len > CRYPTO_MAX_GTK_LEN) return; - } - if (!sm->handshake->wpa_ie) { - gtk_key_index = util_bit_field(gtk[0], 0, 2); - gtk += 2; - gtk_len -= 2; - } else gtk_key_index = ek->wpa_key_id; + } if (sm->handshake->mfp) { igtk = handshake_util_find_igtk_kde(decrypted_key_data, decrypted_key_data_size, &igtk_len); - if (!igtk || igtk_len < 8) + if (!igtk) return; igtk_key_index = l_get_le16(igtk);; diff --git a/src/handshake.c b/src/handshake.c index 2079be50..6dd4a0d4 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -512,8 +512,26 @@ const uint8_t *handshake_util_find_gtk_kde(const uint8_t *data, size_t data_len, size_t *out_gtk_len) { static const unsigned char gtk_oui[] = { 0x00, 0x0f, 0xac, 0x01 }; + size_t gtk_len; + const uint8_t *gtk = find_kde(data, data_len, >k_len, gtk_oui); - return find_kde(data, data_len, out_gtk_len, gtk_oui); + if (!gtk) + return NULL; + + /* + * Account for KeyId, TX and Reserved octet + * See 802.11-2016, Figure 12-35 + */ + if (gtk_len < CRYPTO_MIN_GTK_LEN + 2) + return NULL; + + if (gtk_len > CRYPTO_MAX_GTK_LEN + 2) + return NULL; + + if (out_gtk_len) + *out_gtk_len = gtk_len; + + return gtk; } const uint8_t *handshake_util_find_igtk_kde(const uint8_t *data, @@ -521,8 +539,26 @@ const uint8_t *handshake_util_find_igtk_kde(const uint8_t *data, size_t *out_igtk_len) { static const unsigned char igtk_oui[] = { 0x00, 0x0f, 0xac, 0x09 }; + size_t igtk_len; + const uint8_t *igtk = find_kde(data, data_len, &igtk_len, igtk_oui); - return find_kde(data, data_len, out_igtk_len, igtk_oui); + if (!igtk) + return NULL; + + /* + * Account for KeyId and IPN + * See 802.11-2016, Figure 12-42 + */ + if (igtk_len < CRYPTO_MIN_IGTK_LEN + 8) + return NULL; + + if (igtk_len > CRYPTO_MAX_IGTK_LEN + 8) + return NULL; + + if (out_igtk_len) + *out_igtk_len = igtk_len; + + return igtk; } const uint8_t *handshake_util_find_pmkid_kde(const uint8_t *data,