Supplicant: Add bound check for pmk length and serialized data

When PMK length in setPmkCacheInternal() function deserializes the
input PMK bytes to supplicant rsn_pmk_cache_entry without checking
the input PMK length along with size of input PMK bytes, it results
in an Out-of-Bounds write memory access, causing memory corruption.

Fixes:
1. Adding check for invalid pmk length.

2. A specific size check is added in deserializePmkCacheEntry()
function, where we are checking size of  serializedEntry to the size
of rsn_pmksa_cache_entry structure. If it is less, the invalid input
is rejected and an error message is returned.

Change-Id: I8e80734820e51b018ac63a7bfd5674482be958ee
Bug: 263834889
Test: Manual - connect/disconnect with WPA3 AP and confirmed
      that open authentication with PMK cache works.
diff --git a/wpa_supplicant/aidl/misc_utils.h b/wpa_supplicant/aidl/misc_utils.h
index 5c5b68c..c529e3d 100644
--- a/wpa_supplicant/aidl/misc_utils.h
+++ b/wpa_supplicant/aidl/misc_utils.h
@@ -100,10 +100,21 @@
 	return ss;
 }
 
-inline std::stringstream& deserializePmkCacheEntry(
+inline std::int8_t deserializePmkCacheEntry(
 	std::stringstream &ss, struct rsn_pmksa_cache_entry *pmksa_entry) {
 	ss.seekg(0);
+	if (ss.str().size() < sizeof(pmksa_entry->pmk_len)) {
+		return -1;
+	}
+
 	ss.read((char *) &pmksa_entry->pmk_len, sizeof(pmksa_entry->pmk_len));
+	if ((pmksa_entry->pmk_len > PMK_LEN_MAX) ||
+	    (ss.str().size() < (sizeof(pmksa_entry->pmk_len) + pmksa_entry->pmk_len +
+	    PMKID_LEN + ETH_ALEN + sizeof(pmksa_entry->akmp) +
+	    sizeof(pmksa_entry->reauth_time) + sizeof(pmksa_entry->expiration) +
+	    sizeof(pmksa_entry->opportunistic) + 1 /* fils_cache_id_set */)))
+		return -1;
+
 	ss.read((char *) pmksa_entry->pmk, pmksa_entry->pmk_len);
 	ss.read((char *) pmksa_entry->pmkid, PMKID_LEN);
 	ss.read((char *) pmksa_entry->aa, ETH_ALEN);
@@ -115,8 +126,13 @@
 	char byte = 0;
 	ss.read((char *) &byte, sizeof(byte));
 	pmksa_entry->fils_cache_id_set = (byte) ? 1 : 0;
+	if (pmksa_entry->fils_cache_id_set == 1) {
+		if((ss.str().size() - static_cast<uint32_t>(ss.tellg())) < FILS_CACHE_ID_LEN)
+			return -1;
+	}
+
 	ss.read((char *) pmksa_entry->fils_cache_id, FILS_CACHE_ID_LEN);
-	return ss;
+	return 0;
 }
 }  // namespace misc_utils
 }  // namespace supplicant
diff --git a/wpa_supplicant/aidl/sta_network.cpp b/wpa_supplicant/aidl/sta_network.cpp
index db13509..5a83b05 100644
--- a/wpa_supplicant/aidl/sta_network.cpp
+++ b/wpa_supplicant/aidl/sta_network.cpp
@@ -2158,7 +2158,11 @@
 	std::stringstream ss(
 		std::stringstream::in | std::stringstream::out | std::stringstream::binary);
 	ss.write((char *) serializedEntry.data(), std::streamsize(serializedEntry.size()));
-	misc_utils::deserializePmkCacheEntry(ss, new_entry);
+	if (misc_utils::deserializePmkCacheEntry(ss, new_entry) < 0) {
+		os_free(new_entry);
+		return createStatusWithMsg(SupplicantStatusCode::FAILURE_ARGS_INVALID,
+		 "Invalid pmk length");
+	}
 	new_entry->network_ctx = wpa_ssid;
 
 	// If there is an entry has a later expiration, ignore this one.