Parcourir la source

Clean up EAPOL-Key Key Data processing

Use a single location in wpa_sm_rx_eapol() for preparing the pointer to
the Key Data field and to its validated length instead of fetching that
information in number of processing functions separately.

Signed-off-by: Jouni Malinen <j@w1.fi>
Jouni Malinen il y a 10 ans
Parent
commit
e6270129f6
1 fichiers modifiés avec 59 ajouts et 68 suppressions
  1. 59 68
      src/rsn_supp/wpa.c

+ 59 - 68
src/rsn_supp/wpa.c

@@ -379,7 +379,8 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
 static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
 					  const unsigned char *src_addr,
 					  const struct wpa_eapol_key *key,
-					  u16 ver)
+					  u16 ver, const u8 *key_data,
+					  size_t key_data_len)
 {
 	struct wpa_eapol_ie_parse ie;
 	struct wpa_ptk *ptk;
@@ -401,10 +402,9 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
 
 	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
 		/* RSN: msg 1/4 should contain PMKID for the selected PMK */
-		const u8 *_buf = (const u8 *) (key + 1);
-		size_t len = WPA_GET_BE16(key->key_data_length);
-		wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len);
-		if (wpa_supplicant_parse_ies(_buf, len, &ie) < 0)
+		wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data",
+			    key_data, key_data_len);
+		if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
 			goto failed;
 		if (ie.pmkid) {
 			wpa_hexdump(MSG_DEBUG, "RSN: PMKID from "
@@ -1068,10 +1068,10 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
 
 static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
 					  const struct wpa_eapol_key *key,
-					  u16 ver)
+					  u16 ver, const u8 *key_data,
+					  size_t key_data_len)
 {
-	u16 key_info, keylen, len;
-	const u8 *pos;
+	u16 key_info, keylen;
 	struct wpa_eapol_ie_parse ie;
 
 	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
@@ -1080,10 +1080,8 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
 
 	key_info = WPA_GET_BE16(key->key_info);
 
-	pos = (const u8 *) (key + 1);
-	len = WPA_GET_BE16(key->key_data_length);
-	wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len);
-	if (wpa_supplicant_parse_ies(pos, len, &ie) < 0)
+	wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len);
+	if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
 		goto failed;
 	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
@@ -1238,21 +1236,14 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
 
 static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
 					     const struct wpa_eapol_key *key,
-					     size_t keydatalen, int key_info,
-					     size_t extra_len, u16 ver,
-					     struct wpa_gtk_data *gd)
+					     const u8 *key_data,
+					     size_t key_data_len, u16 key_info,
+					     u16 ver, struct wpa_gtk_data *gd)
 {
 	size_t maxkeylen;
 
 	gd->gtk_len = WPA_GET_BE16(key->key_length);
-	maxkeylen = keydatalen;
-	if (keydatalen > extra_len) {
-		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
-			"WPA: Truncated EAPOL-Key packet: "
-			"key_data_length=%lu > extra_len=%lu",
-			(unsigned long) keydatalen, (unsigned long) extra_len);
-		return -1;
-	}
+	maxkeylen = key_data_len;
 	if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
 		if (maxkeylen < 8) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
@@ -1272,16 +1263,16 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
 		WPA_KEY_INFO_KEY_INDEX_SHIFT;
 	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
 		u8 ek[32];
-		if (keydatalen > sizeof(gd->gtk)) {
+		if (key_data_len > sizeof(gd->gtk)) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: RC4 key data too long (%lu)",
-				(unsigned long) keydatalen);
+				(unsigned long) key_data_len);
 			return -1;
 		}
 		os_memcpy(ek, key->key_iv, 16);
 		os_memcpy(ek + 16, sm->ptk.kek, 16);
-		os_memcpy(gd->gtk, key + 1, keydatalen);
-		if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) {
+		os_memcpy(gd->gtk, key_data, key_data_len);
+		if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) {
 			os_memset(ek, 0, sizeof(ek));
 			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
 				"WPA: RC4 failed");
@@ -1289,22 +1280,21 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
 		}
 		os_memset(ek, 0, sizeof(ek));
 	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
-		if (keydatalen % 8) {
+		if (maxkeylen % 8) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: Unsupported AES-WRAP len %lu",
-				(unsigned long) keydatalen);
+				(unsigned long) maxkeylen);
 			return -1;
 		}
 		if (maxkeylen > sizeof(gd->gtk)) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: AES-WRAP key data "
 				"too long (keydatalen=%lu maxkeylen=%lu)",
-				(unsigned long) keydatalen,
+				(unsigned long) key_data_len,
 				(unsigned long) maxkeylen);
 			return -1;
 		}
-		if (aes_unwrap(sm->ptk.kek, maxkeylen / 8,
-			       (const u8 *) (key + 1), gd->gtk)) {
+		if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, key_data, gd->gtk)) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: AES unwrap failed - could not decrypt "
 				"GTK");
@@ -1360,9 +1350,10 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
 static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
 					  const unsigned char *src_addr,
 					  const struct wpa_eapol_key *key,
-					  int extra_len, u16 ver)
+					  const u8 *key_data,
+					  size_t key_data_len, u16 ver)
 {
-	u16 key_info, keydatalen;
+	u16 key_info;
 	int rekey, ret;
 	struct wpa_gtk_data gd;
 
@@ -1373,17 +1364,15 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
 		"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
 
 	key_info = WPA_GET_BE16(key->key_info);
-	keydatalen = WPA_GET_BE16(key->key_data_length);
 
 	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
-		ret = wpa_supplicant_process_1_of_2_rsn(sm,
-							(const u8 *) (key + 1),
-							keydatalen, key_info,
+		ret = wpa_supplicant_process_1_of_2_rsn(sm, key_data,
+							key_data_len, key_info,
 							&gd);
 	} else {
-		ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen,
-							key_info, extra_len,
-							ver, &gd);
+		ret = wpa_supplicant_process_1_of_2_wpa(sm, key, key_data,
+							key_data_len,
+							key_info, ver, &gd);
 	}
 
 	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
@@ -1471,12 +1460,11 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
 
 /* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
 static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
-					   struct wpa_eapol_key *key, u16 ver)
+					   struct wpa_eapol_key *key, u16 ver,
+					   u8 *key_data, size_t *key_data_len)
 {
-	u16 keydatalen = WPA_GET_BE16(key->key_data_length);
-
 	wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
-		    (u8 *) (key + 1), keydatalen);
+		    key_data, *key_data_len);
 	if (!sm->ptk_set) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"WPA: PTK not available, cannot decrypt EAPOL-Key Key "
@@ -1490,7 +1478,7 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
 		u8 ek[32];
 		os_memcpy(ek, key->key_iv, 16);
 		os_memcpy(ek + 16, sm->ptk.kek, 16);
-		if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) {
+		if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) {
 			os_memset(ek, 0, sizeof(ek));
 			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
 				"WPA: RC4 failed");
@@ -1501,37 +1489,37 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
 		   ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
 		   sm->key_mgmt == WPA_KEY_MGMT_OSEN) {
 		u8 *buf;
-		if (keydatalen < 8 || keydatalen % 8) {
+		if (*key_data_len < 8 || *key_data_len % 8) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
-				"WPA: Unsupported AES-WRAP len %d",
-				keydatalen);
+				"WPA: Unsupported AES-WRAP len %u",
+				(unsigned int) *key_data_len);
 			return -1;
 		}
-		keydatalen -= 8; /* AES-WRAP adds 8 bytes */
-		buf = os_malloc(keydatalen);
+		*key_data_len -= 8; /* AES-WRAP adds 8 bytes */
+		buf = os_malloc(*key_data_len);
 		if (buf == NULL) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: No memory for AES-UNWRAP buffer");
 			return -1;
 		}
-		if (aes_unwrap(sm->ptk.kek, keydatalen / 8,
-			       (u8 *) (key + 1), buf)) {
+		if (aes_unwrap(sm->ptk.kek, *key_data_len / 8,
+			       key_data, buf)) {
 			os_free(buf);
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: AES unwrap failed - "
 				"could not decrypt EAPOL-Key key data");
 			return -1;
 		}
-		os_memcpy(key + 1, buf, keydatalen);
+		os_memcpy(key_data, buf, *key_data_len);
 		os_free(buf);
-		WPA_PUT_BE16(key->key_data_length, keydatalen);
+		WPA_PUT_BE16(key->key_data_length, *key_data_len);
 	} else {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"WPA: Unsupported key_info type %d", ver);
 		return -1;
 	}
 	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
-			(u8 *) (key + 1), keydatalen);
+			key_data, *key_data_len);
 	return 0;
 }
 
@@ -1605,13 +1593,14 @@ static void wpa_eapol_key_dump(struct wpa_sm *sm,
 int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 		    const u8 *buf, size_t len)
 {
-	size_t plen, data_len, extra_len;
+	size_t plen, data_len, key_data_len;
 	const struct ieee802_1x_hdr *hdr;
 	struct wpa_eapol_key *key;
 	u16 key_info, ver;
 	u8 *tmp = NULL;
 	int ret = -1;
 	struct wpa_peerkey *peerkey = NULL;
+	u8 *key_data;
 
 #ifdef CONFIG_IEEE80211R
 	sm->ft_completed = 0;
@@ -1667,6 +1656,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 		goto out;
 	os_memcpy(tmp, buf, data_len);
 	key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr));
+	key_data = (u8 *) (key + 1);
 
 	if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
 	{
@@ -1678,11 +1668,11 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 	}
 	wpa_eapol_key_dump(sm, key);
 
-	extra_len = WPA_GET_BE16(key->key_data_length);
-	if (extra_len > plen - sizeof(struct wpa_eapol_key)) {
+	key_data_len = WPA_GET_BE16(key->key_data_length);
+	if (key_data_len > plen - sizeof(struct wpa_eapol_key)) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
 			"frame - key_data overflow (%u > %u)",
-			(unsigned int) extra_len,
+			(unsigned int) key_data_len,
 			(unsigned int) (plen - sizeof(struct wpa_eapol_key)));
 		goto out;
 	}
@@ -1829,10 +1819,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 
 	if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
 	    (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
-		if (wpa_supplicant_decrypt_key_data(sm, key, ver))
-			goto out;
-		extra_len = WPA_GET_BE16(key->key_data_length);
-		if (extra_len > plen - sizeof(struct wpa_eapol_key))
+		if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data,
+						    &key_data_len))
 			goto out;
 	}
 
@@ -1848,21 +1836,24 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 			peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver);
 		} else if (key_info & WPA_KEY_INFO_MIC) {
 			/* 3/4 4-Way Handshake */
-			wpa_supplicant_process_3_of_4(sm, key, ver);
+			wpa_supplicant_process_3_of_4(sm, key, ver, key_data,
+						      key_data_len);
 		} else {
 			/* 1/4 4-Way Handshake */
 			wpa_supplicant_process_1_of_4(sm, src_addr, key,
-						      ver);
+						      ver, key_data,
+						      key_data_len);
 		}
 	} else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
 		/* PeerKey SMK Handshake */
-		peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info,
+		peerkey_rx_eapol_smk(sm, src_addr, key, key_data_len, key_info,
 				     ver);
 	} else {
 		if (key_info & WPA_KEY_INFO_MIC) {
 			/* 1/2 Group Key Handshake */
 			wpa_supplicant_process_1_of_2(sm, src_addr, key,
-						      extra_len, ver);
+						      key_data, key_data_len,
+						      ver);
 		} else {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: EAPOL-Key (Group) without Mic bit - "