summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java42
-rw-r--r--wifi/java/android/net/wifi/hotspot2/pps/Credential.java24
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java40
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java138
4 files changed, 204 insertions, 40 deletions
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 71d4173a389c..26bdb181e4a1 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -20,10 +20,10 @@ import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
+import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
-import android.os.Parcel;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@@ -467,24 +467,54 @@ public final class PasspointConfiguration implements Parcelable {
}
/**
- * Validate the configuration data.
+ * Validate the R1 configuration data.
*
* @return true on success or false on failure
* @hide
*/
public boolean validate() {
- if (mHomeSp == null || !mHomeSp.validate()) {
+ // Optional: PerProviderSubscription/<X+>/SubscriptionUpdate
+ if (mSubscriptionUpdate != null && !mSubscriptionUpdate.validate()) {
return false;
}
- if (mCredential == null || !mCredential.validate()) {
+ return validateForCommonR1andR2(true);
+ }
+
+ /**
+ * Validate the R2 configuration data.
+ *
+ * @return true on success or false on failure
+ * @hide
+ */
+ public boolean validateForR2() {
+ // Required: PerProviderSubscription/UpdateIdentifier
+ if (mUpdateIdentifier == Integer.MIN_VALUE) {
return false;
}
- if (mPolicy != null && !mPolicy.validate()) {
+
+ // Required: PerProviderSubscription/<X+>/SubscriptionUpdate
+ if (mSubscriptionUpdate == null || !mSubscriptionUpdate.validate()) {
return false;
}
- if (mSubscriptionUpdate != null && !mSubscriptionUpdate.validate()) {
+ return validateForCommonR1andR2(false);
+ }
+
+ private boolean validateForCommonR1andR2(boolean isR1) {
+ // Required: PerProviderSubscription/<X+>/HomeSP
+ if (mHomeSp == null || !mHomeSp.validate()) {
+ return false;
+ }
+
+ // Required: PerProviderSubscription/<X+>/Credential
+ if (mCredential == null || !mCredential.validate(isR1)) {
+ return false;
+ }
+
+ // Optional: PerProviderSubscription/<X+>/Policy
+ if (mPolicy != null && !mPolicy.validate()) {
return false;
}
+
if (mTrustRootCertList != null) {
for (Map.Entry<String, byte[]> entry : mTrustRootCertList.entrySet()) {
String url = entry.getKey();
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index e8fcbfd6731e..7689fc34ff5b 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -18,8 +18,8 @@ package android.net.wifi.hotspot2.pps;
import android.net.wifi.EAPConstants;
import android.net.wifi.ParcelUtil;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
@@ -1019,10 +1019,11 @@ public final class Credential implements Parcelable {
/**
* Validate the configuration data.
*
+ * @param isR1 {@code true} if the configuration is for R1
* @return true on success or false on failure
* @hide
*/
- public boolean validate() {
+ public boolean validate(boolean isR1) {
if (TextUtils.isEmpty(mRealm)) {
Log.d(TAG, "Missing realm");
return false;
@@ -1035,11 +1036,11 @@ public final class Credential implements Parcelable {
// Verify the credential.
if (mUserCredential != null) {
- if (!verifyUserCredential()) {
+ if (!verifyUserCredential(isR1)) {
return false;
}
} else if (mCertCredential != null) {
- if (!verifyCertCredential()) {
+ if (!verifyCertCredential(isR1)) {
return false;
}
} else if (mSimCredential != null) {
@@ -1081,9 +1082,10 @@ public final class Credential implements Parcelable {
/**
* Verify user credential.
*
+ * @param isR1 {@code true} if credential is for R1
* @return true if user credential is valid, false otherwise.
*/
- private boolean verifyUserCredential() {
+ private boolean verifyUserCredential(boolean isR1) {
if (mUserCredential == null) {
Log.d(TAG, "Missing user credential");
return false;
@@ -1095,7 +1097,10 @@ public final class Credential implements Parcelable {
if (!mUserCredential.validate()) {
return false;
}
- if (mCaCertificate == null) {
+
+ // CA certificate is required for R1 Passpoint profile.
+ // For R2, it is downloaded using cert URL provided in PPS MO after validation completes.
+ if (isR1 && mCaCertificate == null) {
Log.d(TAG, "Missing CA Certificate for user credential");
return false;
}
@@ -1106,9 +1111,10 @@ public final class Credential implements Parcelable {
* Verify certificate credential, which is used for EAP-TLS. This will verify
* that the necessary client key and certificates are provided.
*
+ * @param isR1 {@code true} if credential is for R1
* @return true if certificate credential is valid, false otherwise.
*/
- private boolean verifyCertCredential() {
+ private boolean verifyCertCredential(boolean isR1) {
if (mCertCredential == null) {
Log.d(TAG, "Missing certificate credential");
return false;
@@ -1123,7 +1129,9 @@ public final class Credential implements Parcelable {
}
// Verify required key and certificates for certificate credential.
- if (mCaCertificate == null) {
+ // CA certificate is required for R1 Passpoint profile.
+ // For R2, it is downloaded using cert URL provided in PPS MO after validation completes.
+ if (isR1 && mCaCertificate == null) {
Log.d(TAG, "Missing CA Certificate for certificate credential");
return false;
}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 940adc809535..775ce21656f7 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -146,6 +146,7 @@ public class PasspointConfigurationTest {
*/
private static PasspointConfiguration createConfig() {
PasspointConfiguration config = new PasspointConfiguration();
+ config.setUpdateIdentifier(1234);
config.setHomeSp(createHomeSp());
config.setCredential(createCredential());
config.setPolicy(createPolicy());
@@ -273,18 +274,37 @@ public class PasspointConfigurationTest {
@Test
public void validateDefaultConfig() throws Exception {
PasspointConfiguration config = new PasspointConfiguration();
+
assertFalse(config.validate());
+ assertFalse(config.validateForR2());
}
/**
- * Verify that a configuration contained all fields is valid.
+ * Verify that a configuration containing all fields is valid for R1/R2.
*
* @throws Exception
*/
@Test
public void validateFullConfig() throws Exception {
PasspointConfiguration config = createConfig();
+
+ assertTrue(config.validate());
+ assertTrue(config.validateForR2());
+ }
+
+ /**
+ * Verify that a configuration containing all fields except for UpdateIdentifier is valid for
+ * R1, but invalid for R2.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateFullConfigWithoutUpdateIdentifier() throws Exception {
+ PasspointConfiguration config = createConfig();
+ config.setUpdateIdentifier(Integer.MIN_VALUE);
+
assertTrue(config.validate());
+ assertFalse(config.validateForR2());
}
/**
@@ -296,7 +316,9 @@ public class PasspointConfigurationTest {
public void validateConfigWithoutCredential() throws Exception {
PasspointConfiguration config = createConfig();
config.setCredential(null);
+
assertFalse(config.validate());
+ assertFalse(config.validateForR2());
}
/**
@@ -308,12 +330,14 @@ public class PasspointConfigurationTest {
public void validateConfigWithoutHomeSp() throws Exception {
PasspointConfiguration config = createConfig();
config.setHomeSp(null);
+
assertFalse(config.validate());
+ assertFalse(config.validateForR2());
}
/**
* Verify that a configuration without Policy is valid, since Policy configurations
- * are optional (applied for Hotspot 2.0 Release only).
+ * are optional for R1 and R2.
*
* @throws Exception
*/
@@ -321,12 +345,14 @@ public class PasspointConfigurationTest {
public void validateConfigWithoutPolicy() throws Exception {
PasspointConfiguration config = createConfig();
config.setPolicy(null);
+
assertTrue(config.validate());
+ assertTrue(config.validateForR2());
}
/**
- * Verify that a configuration without subscription update is valid, since subscription
- * update configurations are optional (applied for Hotspot 2.0 Release only).
+ * Verify that a configuration without subscription update is valid for R1 and invalid for R2,
+ * since subscription update configuration is only applicable for R2.
*
* @throws Exception
*/
@@ -334,7 +360,9 @@ public class PasspointConfigurationTest {
public void validateConfigWithoutSubscriptionUpdate() throws Exception {
PasspointConfiguration config = createConfig();
config.setSubscriptionUpdate(null);
+
assertTrue(config.validate());
+ assertFalse(config.validateForR2());
}
/**
@@ -352,12 +380,15 @@ public class PasspointConfigurationTest {
trustRootCertList.put(new String(rawUrlBytes, StandardCharsets.UTF_8),
new byte[CERTIFICATE_FINGERPRINT_BYTES]);
config.setTrustRootCertList(trustRootCertList);
+
assertFalse(config.validate());
trustRootCertList = new HashMap<>();
trustRootCertList.put(null, new byte[CERTIFICATE_FINGERPRINT_BYTES]);
config.setTrustRootCertList(trustRootCertList);
+
assertFalse(config.validate());
+ assertFalse(config.validateForR2());
}
/**
@@ -382,6 +413,7 @@ public class PasspointConfigurationTest {
trustRootCertList.put("test.cert.com", null);
config.setTrustRootCertList(trustRootCertList);
assertFalse(config.validate());
+ assertFalse(config.validateForR2());
}
/**
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index c5ad7de12d19..c07db6c323a2 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -24,14 +24,13 @@ import android.net.wifi.FakeKeys;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
+import org.junit.Test;
+
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
-import java.util.Arrays;
-
-import org.junit.Test;
/**
* Unit tests for {@link android.net.wifi.hotspot2.pps.CredentialTest}.
@@ -169,7 +168,12 @@ public class CredentialTest {
@Test
public void validateUserCredential() throws Exception {
Credential cred = createCredentialWithUserCredential();
- assertTrue(cred.validate());
+
+ // For R1 validation
+ assertTrue(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -181,7 +185,12 @@ public class CredentialTest {
public void validateUserCredentialWithoutCaCert() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.setCaCertificate(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -193,7 +202,12 @@ public class CredentialTest {
public void validateUserCredentialWithEapTls() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.getUserCredential().setEapType(EAPConstants.EAP_TLS);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
@@ -206,7 +220,12 @@ public class CredentialTest {
public void validateUserCredentialWithoutRealm() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.setRealm(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -218,7 +237,12 @@ public class CredentialTest {
public void validateUserCredentialWithoutUsername() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.getUserCredential().setUsername(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -230,7 +254,12 @@ public class CredentialTest {
public void validateUserCredentialWithoutPassword() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.getUserCredential().setPassword(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -242,7 +271,12 @@ public class CredentialTest {
public void validateUserCredentialWithoutAuthMethod() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.getUserCredential().setNonEapInnerMethod(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -255,7 +289,12 @@ public class CredentialTest {
@Test
public void validateCertCredential() throws Exception {
Credential cred = createCredentialWithCertificateCredential();
- assertTrue(cred.validate());
+
+ // For R1 validation
+ assertTrue(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(true));
}
/**
@@ -267,7 +306,12 @@ public class CredentialTest {
public void validateCertCredentialWithoutCaCert() throws Exception {
Credential cred = createCredentialWithCertificateCredential();
cred.setCaCertificate(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -279,7 +323,12 @@ public class CredentialTest {
public void validateCertCredentialWithoutClientCertChain() throws Exception {
Credential cred = createCredentialWithCertificateCredential();
cred.setClientCertificateChain(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -291,7 +340,12 @@ public class CredentialTest {
public void validateCertCredentialWithoutClientPrivateKey() throws Exception {
Credential cred = createCredentialWithCertificateCredential();
cred.setClientPrivateKey(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -304,7 +358,12 @@ public class CredentialTest {
public void validateCertCredentialWithMismatchFingerprint() throws Exception {
Credential cred = createCredentialWithCertificateCredential();
cred.getCertCredential().setCertSha256Fingerprint(new byte[32]);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -315,7 +374,12 @@ public class CredentialTest {
@Test
public void validateSimCredentialWithEapSim() throws Exception {
Credential cred = createCredentialWithSimCredential();
- assertTrue(cred.validate());
+
+ // For R1 validation
+ assertTrue(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -327,7 +391,12 @@ public class CredentialTest {
public void validateSimCredentialWithEapAka() throws Exception {
Credential cred = createCredentialWithSimCredential();
cred.getSimCredential().setEapType(EAPConstants.EAP_AKA);
- assertTrue(cred.validate());
+
+ // For R1 validation
+ assertTrue(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -339,7 +408,12 @@ public class CredentialTest {
public void validateSimCredentialWithEapAkaPrime() throws Exception {
Credential cred = createCredentialWithSimCredential();
cred.getSimCredential().setEapType(EAPConstants.EAP_AKA_PRIME);
- assertTrue(cred.validate());
+
+ // For R1 validation
+ assertTrue(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -351,7 +425,12 @@ public class CredentialTest {
public void validateSimCredentialWithoutIMSI() throws Exception {
Credential cred = createCredentialWithSimCredential();
cred.getSimCredential().setImsi(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -363,7 +442,12 @@ public class CredentialTest {
public void validateSimCredentialWithInvalidIMSI() throws Exception {
Credential cred = createCredentialWithSimCredential();
cred.getSimCredential().setImsi("dummy");
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -375,7 +459,12 @@ public class CredentialTest {
public void validateSimCredentialWithEapTls() throws Exception {
Credential cred = createCredentialWithSimCredential();
cred.getSimCredential().setEapType(EAPConstants.EAP_TLS);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -391,7 +480,12 @@ public class CredentialTest {
simCredential.setImsi("1234*");
simCredential.setEapType(EAPConstants.EAP_SIM);
cred.setSimCredential(simCredential);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**