[Passpoint] Add more check to limit the config size

Bug: 245299920
Test: atest con.android.server.wifi
Merged-In: I97522ce3607547c10025caa107cd1a40455a9c5d
Change-Id: I97522ce3607547c10025caa107cd1a40455a9c5d
(cherry picked from commit c13de6409ec5f781582f0c137bd63626501c6c58)
Merged-In: I97522ce3607547c10025caa107cd1a40455a9c5d
diff --git a/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 239f406..60c8133 100644
--- a/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -70,8 +70,42 @@
 
     /**
      * Maximum bytes for URL string.
+     * @hide
      */
-    private static final int MAX_URL_BYTES = 1023;
+    public static final int MAX_URL_BYTES = 2048;
+
+    /**
+     * Maximum size for match entry, just to limit the size of the Passpoint config.
+     * @hide
+     */
+    public static final int MAX_NUMBER_OF_ENTRIES = 16;
+
+    /**
+     * Maximum size for OI entry.
+     * The spec allows a string of up to 255 characters, with comma delimited numbers like
+     * 001122,334455. So with minimum OI size of 7, the maximum amount of OIs is 36.
+     * @hide
+     */
+    public static final int MAX_NUMBER_OF_OI = 36;
+
+
+    /**
+     * Maximum bytes for a string entry like FQDN and friendly name.
+     * @hide
+     */
+    public static final int MAX_STRING_LENGTH = 255;
+
+    /**
+     * HESSID is 48 bit.
+     * @hide
+     */
+    public static final long MAX_HESSID_VALUE = ((long) 1 << 48)  - 1;
+
+    /**
+     * Organization Identifiers is 3 or 5 Octets. 24 or 36 bit.
+     * @hide
+     */
+    public static final long MAX_OI_VALUE = ((long) 1 << 40)  - 1;
 
     /**
      * Integer value used for indicating null value in the Parcel.
@@ -954,14 +988,49 @@
             return false;
         }
         // Optional: DecoratedIdentityPrefix
-        if (!TextUtils.isEmpty(mDecoratedIdentityPrefix)
-                && !mDecoratedIdentityPrefix.endsWith("!")) {
-            EventLog.writeEvent(0x534e4554, "246539931", -1,
+        if (!TextUtils.isEmpty(mDecoratedIdentityPrefix)) {
+            if (!mDecoratedIdentityPrefix.endsWith("!")) {
+                EventLog.writeEvent(0x534e4554, "246539931", -1,
                     "Invalid decorated identity prefix");
-            return false;
+                return false;
+            }
+            String[] decoratedIdentityPrefixArray = mDecoratedIdentityPrefix.split("!");
+            if (decoratedIdentityPrefixArray.length > MAX_NUMBER_OF_ENTRIES) {
+                Log.d(TAG, "too many decoratedIdentityPrefix");
+                return false;
+            }
+            for (String prefix : decoratedIdentityPrefixArray) {
+                if (prefix.length() > MAX_STRING_LENGTH) {
+                    Log.d(TAG, "The decoratedIdentityPrefix is too long: " + prefix);
+                    return false;
+                }
+            }
+        }
+
+        if (mAaaServerTrustedNames != null) {
+            if (mAaaServerTrustedNames.length > MAX_NUMBER_OF_ENTRIES) {
+                Log.d(TAG, "Too many AaaServerTrustedNames");
+                return false;
+            }
+            for (String fqdn : mAaaServerTrustedNames) {
+                if (fqdn.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+                    Log.d(TAG, "AaaServerTrustedNames is too long");
+                    return false;
+                }
+            }
+        }
+        if (mSubscriptionType != null) {
+            if (mSubscriptionType.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+                Log.d(TAG, "SubscriptionType is too long");
+                return false;
+            }
         }
 
         if (mTrustRootCertList != null) {
+            if (mTrustRootCertList.size() > MAX_NUMBER_OF_ENTRIES) {
+                Log.d(TAG, "Too many TrustRootCert");
+                return false;
+            }
             for (Map.Entry<String, byte[]> entry : mTrustRootCertList.entrySet()) {
                 String url = entry.getKey();
                 byte[] certFingerprint = entry.getValue();
diff --git a/framework/java/android/net/wifi/hotspot2/pps/Credential.java b/framework/java/android/net/wifi/hotspot2/pps/Credential.java
index 282757a..4ca724a 100644
--- a/framework/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/framework/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -16,6 +16,8 @@
 
 package android.net.wifi.hotspot2.pps;
 
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH;
+
 import android.net.wifi.EAPConstants;
 import android.net.wifi.ParcelUtil;
 import android.os.Parcel;
@@ -413,6 +415,13 @@
                         + mPassword.getBytes(StandardCharsets.UTF_8).length);
                 return false;
             }
+            if (mSoftTokenApp != null) {
+                if (mSoftTokenApp.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+                    Log.d(TAG, "app name exceeding maximum length: "
+                            + mSoftTokenApp.getBytes(StandardCharsets.UTF_8).length);
+                    return false;
+                }
+            }
 
             // Only supports EAP-TTLS for user credential.
             if (mEapType != EAPConstants.EAP_TTLS) {
diff --git a/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java b/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 64aad61..34aff6c 100644
--- a/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java
+++ b/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -16,6 +16,13 @@
 
 package android.net.wifi.hotspot2.pps;
 
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_HESSID_VALUE;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_ENTRIES;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_OI;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_OI_VALUE;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_URL_BYTES;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
@@ -404,16 +411,86 @@
             Log.d(TAG, "Missing FQDN");
             return false;
         }
+        if (mFqdn.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+            Log.d(TAG, "FQDN is too long");
+            return false;
+        }
         if (TextUtils.isEmpty(mFriendlyName)) {
             Log.d(TAG, "Missing friendly name");
             return false;
         }
+        if (mFriendlyName.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+            Log.d(TAG, "Friendly name is too long");
+            return false;
+        }
         // Verify SSIDs specified in the NetworkID
         if (mHomeNetworkIds != null) {
+            if (mHomeNetworkIds.size() > MAX_NUMBER_OF_ENTRIES) {
+                Log.d(TAG, "too many SSID in HomeNetworkIDs");
+                return false;
+            }
             for (Map.Entry<String, Long> entry : mHomeNetworkIds.entrySet()) {
                 if (entry.getKey() == null ||
                         entry.getKey().getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) {
-                    Log.d(TAG, "Invalid SSID in HomeNetworkIDs");
+                    Log.d(TAG, "SSID is too long in HomeNetworkIDs");
+                    return false;
+                }
+                if (entry.getValue() != null
+                        && (entry.getValue() > MAX_HESSID_VALUE || entry.getValue() < 0)) {
+                    Log.d(TAG, "HESSID is out of range");
+                    return false;
+                }
+            }
+        }
+        if (mIconUrl != null && mIconUrl.getBytes(StandardCharsets.UTF_8).length > MAX_URL_BYTES) {
+            Log.d(TAG, "Icon URL is too long");
+            return false;
+        }
+        if (mMatchAllOis != null) {
+            if (mMatchAllOis.length > MAX_NUMBER_OF_OI) {
+                Log.d(TAG, "too many match all Organization Identifiers in the profile");
+                return false;
+            }
+            for (long oi : mMatchAllOis) {
+                if (oi > MAX_OI_VALUE || oi < 0) {
+                    Log.d(TAG, "Organization Identifiers is out of range");
+                    return false;
+                }
+            }
+        }
+        if (mMatchAnyOis != null) {
+            if (mMatchAnyOis.length > MAX_NUMBER_OF_OI) {
+                Log.d(TAG, "too many match any Organization Identifiers in the profile");
+                return false;
+            }
+            for (long oi : mMatchAnyOis) {
+                if (oi > MAX_OI_VALUE || oi < 0) {
+                    Log.d(TAG, "Organization Identifiers is out of range");
+                    return false;
+                }
+            }
+        }
+        if (mRoamingConsortiumOis != null) {
+            if (mRoamingConsortiumOis.length > MAX_NUMBER_OF_OI) {
+                Log.d(TAG, "too many Roaming Consortium Organization Identifiers in the "
+                        + "profile");
+                return false;
+            }
+            for (long oi : mRoamingConsortiumOis) {
+                if (oi > MAX_OI_VALUE || oi < 0) {
+                    Log.d(TAG, "Organization Identifiers is out of range");
+                    return false;
+                }
+            }
+        }
+        if (mOtherHomePartners != null) {
+            if (mOtherHomePartners.length > MAX_NUMBER_OF_ENTRIES) {
+                Log.d(TAG, "too many other home partners in the profile");
+                return false;
+            }
+            for (String fqdn : mOtherHomePartners) {
+                if (fqdn.length() > MAX_STRING_LENGTH) {
+                    Log.d(TAG, "FQDN is too long in OtherHomePartners");
                     return false;
                 }
             }
diff --git a/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index d8393f9..5450e3d 100644
--- a/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -53,7 +53,7 @@
  */
 @SmallTest
 public class PasspointConfigurationTest {
-    private static final int MAX_URL_BYTES = 1023;
+    private static final int MAX_URL_BYTES = 2048;
     private static final int CERTIFICATE_FINGERPRINT_BYTES = 32;
     private static final String TEST_DECORATED_IDENTITY_PREFIX = "androidwifi.dev!";
     private static final long SUBSCRIPTION_EXPIRATION_TIME_MS = 1643996661000L;