1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package android.net.wifi; 18 19 import static org.junit.Assert.assertArrayEquals; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertNotEquals; 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertNull; 25 import static org.junit.Assert.assertThrows; 26 import static org.junit.Assert.assertTrue; 27 import static org.junit.Assert.fail; 28 import static org.junit.Assume.assumeTrue; 29 import static org.mockito.Mockito.mock; 30 import static org.mockito.Mockito.when; 31 32 import android.net.wifi.WifiEnterpriseConfig.Eap; 33 import android.net.wifi.WifiEnterpriseConfig.Phase2; 34 import android.net.wifi.hotspot2.PasspointConfiguration; 35 import android.os.Bundle; 36 import android.os.Parcel; 37 import android.security.Credentials; 38 39 import androidx.test.filters.SmallTest; 40 41 import com.android.modules.utils.build.SdkLevel; 42 43 import org.junit.Before; 44 import org.junit.Test; 45 46 import java.security.PrivateKey; 47 import java.security.cert.X509Certificate; 48 import java.util.Arrays; 49 import java.util.HashMap; 50 import java.util.Map; 51 52 /** 53 * Unit tests for {@link android.net.wifi.WifiEnterpriseConfig}. 54 */ 55 @SmallTest 56 public class WifiEnterpriseConfigTest { 57 // Maintain a ground truth of the keystore uri prefix which is expected by wpa_supplicant. 58 public static final String KEYSTORE_URI = "keystore://"; 59 public static final String CA_CERT_PREFIX = KEYSTORE_URI + Credentials.CA_CERTIFICATE; 60 public static final String KEYSTORES_URI = "keystores://"; 61 private static final String TEST_DOMAIN_SUFFIX_MATCH = "domainSuffixMatch"; 62 private static final String TEST_ALT_SUBJECT_MATCH = "DNS:server.test.com"; 63 private static final String TEST_DECORATED_IDENTITY_PREFIX = "androidwifi.dev!"; 64 private static final long TEST_SELECTED_RCOI = 0xcafeL; 65 66 private WifiEnterpriseConfig mEnterpriseConfig; 67 68 @Before setUp()69 public void setUp() throws Exception { 70 mEnterpriseConfig = new WifiEnterpriseConfig(); 71 } 72 73 @Test testGetEmptyCaCertificate()74 public void testGetEmptyCaCertificate() { 75 // A newly-constructed WifiEnterpriseConfig object should have no CA certificate. 76 assertNull(mEnterpriseConfig.getCaCertificate()); 77 assertNull(mEnterpriseConfig.getCaCertificates()); 78 // Setting CA certificate to null explicitly. 79 mEnterpriseConfig.setCaCertificate(null); 80 assertNull(mEnterpriseConfig.getCaCertificate()); 81 // Setting CA certificate to null using setCaCertificates(). 82 mEnterpriseConfig.setCaCertificates(null); 83 assertNull(mEnterpriseConfig.getCaCertificates()); 84 // Setting CA certificate to zero-length array. 85 mEnterpriseConfig.setCaCertificates(new X509Certificate[0]); 86 assertNull(mEnterpriseConfig.getCaCertificates()); 87 } 88 89 @Test testSetGetSingleCaCertificate()90 public void testSetGetSingleCaCertificate() { 91 X509Certificate cert0 = FakeKeys.CA_CERT0; 92 mEnterpriseConfig.setCaCertificate(cert0); 93 assertEquals(mEnterpriseConfig.getCaCertificate(), cert0); 94 } 95 96 @Test testSetGetMultipleCaCertificates()97 public void testSetGetMultipleCaCertificates() { 98 X509Certificate cert0 = FakeKeys.CA_CERT0; 99 X509Certificate cert1 = FakeKeys.CA_CERT1; 100 mEnterpriseConfig.setCaCertificates(new X509Certificate[] {cert0, cert1}); 101 X509Certificate[] result = mEnterpriseConfig.getCaCertificates(); 102 assertEquals(result.length, 2); 103 assertTrue(result[0] == cert0 && result[1] == cert1); 104 } 105 106 @Test testSetGetInvalidNumberOfCaCertificates()107 public void testSetGetInvalidNumberOfCaCertificates() { 108 // Maximum number of CA certificates is 100. 109 X509Certificate[] invalidCaCertList = new X509Certificate[105]; 110 Arrays.fill(invalidCaCertList, FakeKeys.CA_CERT0); 111 assertThrows(IllegalArgumentException.class, () -> { 112 mEnterpriseConfig.setCaCertificates(invalidCaCertList); 113 }); 114 assertEquals(null, mEnterpriseConfig.getCaCertificates()); 115 } 116 117 @Test testSetClientKeyEntryWithNull()118 public void testSetClientKeyEntryWithNull() { 119 mEnterpriseConfig.setClientKeyEntry(null, null); 120 assertNull(mEnterpriseConfig.getClientCertificateChain()); 121 assertNull(mEnterpriseConfig.getClientCertificate()); 122 mEnterpriseConfig.setClientKeyEntryWithCertificateChain(null, null); 123 assertNull(mEnterpriseConfig.getClientCertificateChain()); 124 assertNull(mEnterpriseConfig.getClientCertificate()); 125 126 // Setting the client certificate to null should clear the existing chain. 127 PrivateKey clientKey = FakeKeys.RSA_KEY1; 128 X509Certificate clientCert0 = FakeKeys.CLIENT_CERT; 129 X509Certificate clientCert1 = FakeKeys.CA_CERT1; 130 mEnterpriseConfig.setClientKeyEntry(clientKey, clientCert0); 131 assertNotNull(mEnterpriseConfig.getClientCertificate()); 132 mEnterpriseConfig.setClientKeyEntry(null, null); 133 assertNull(mEnterpriseConfig.getClientCertificate()); 134 assertNull(mEnterpriseConfig.getClientCertificateChain()); 135 136 // Setting the chain to null should clear the existing chain. 137 X509Certificate[] clientChain = new X509Certificate[] {clientCert0, clientCert1}; 138 mEnterpriseConfig.setClientKeyEntryWithCertificateChain(clientKey, clientChain); 139 assertNotNull(mEnterpriseConfig.getClientCertificateChain()); 140 mEnterpriseConfig.setClientKeyEntryWithCertificateChain(null, null); 141 assertNull(mEnterpriseConfig.getClientCertificate()); 142 assertNull(mEnterpriseConfig.getClientCertificateChain()); 143 } 144 145 @Test testSetClientCertificateChain()146 public void testSetClientCertificateChain() { 147 PrivateKey clientKey = FakeKeys.RSA_KEY1; 148 X509Certificate cert0 = FakeKeys.CLIENT_CERT; 149 X509Certificate cert1 = FakeKeys.CA_CERT1; 150 X509Certificate[] clientChain = new X509Certificate[] {cert0, cert1}; 151 mEnterpriseConfig.setClientKeyEntryWithCertificateChain(clientKey, clientChain); 152 X509Certificate[] result = mEnterpriseConfig.getClientCertificateChain(); 153 assertEquals(result.length, 2); 154 assertTrue(result[0] == cert0 && result[1] == cert1); 155 assertTrue(mEnterpriseConfig.getClientCertificate() == cert0); 156 } 157 158 @Test testSetGetClientKeyPairAlias()159 public void testSetGetClientKeyPairAlias() { 160 assumeTrue(SdkLevel.isAtLeastS()); 161 162 final String alias = "alias"; 163 mEnterpriseConfig.setClientKeyPairAlias(alias); 164 assertEquals(alias, mEnterpriseConfig.getClientKeyPairAlias()); 165 assertEquals(alias, mEnterpriseConfig.getClientKeyPairAliasInternal()); 166 167 // Alias should have a maximum length of 256. 168 final String invalidAlias = "*".repeat(1000); 169 assertThrows(IllegalArgumentException.class, () -> { 170 mEnterpriseConfig.setClientKeyPairAlias(invalidAlias); 171 }); 172 } 173 isClientCertificateChainInvalid(X509Certificate[] clientChain)174 private boolean isClientCertificateChainInvalid(X509Certificate[] clientChain) { 175 boolean exceptionThrown = false; 176 try { 177 PrivateKey clientKey = FakeKeys.RSA_KEY1; 178 mEnterpriseConfig.setClientKeyEntryWithCertificateChain(clientKey, clientChain); 179 } catch (IllegalArgumentException e) { 180 exceptionThrown = true; 181 } 182 return exceptionThrown; 183 } 184 185 @Test testSetInvalidClientCertificateChain()186 public void testSetInvalidClientCertificateChain() { 187 X509Certificate clientCert = FakeKeys.CLIENT_CERT; 188 X509Certificate caCert = FakeKeys.CA_CERT1; 189 assertTrue("Invalid client certificate", 190 isClientCertificateChainInvalid(new X509Certificate[] {caCert, caCert})); 191 assertTrue("Invalid CA certificate", 192 isClientCertificateChainInvalid(new X509Certificate[] {clientCert, clientCert})); 193 assertTrue("Both certificates invalid", 194 isClientCertificateChainInvalid(new X509Certificate[] {caCert, clientCert})); 195 assertTrue("Certificate chain contains too many elements", 196 isClientCertificateChainInvalid(new X509Certificate[] { 197 clientCert, clientCert, clientCert, clientCert, caCert, caCert})); 198 } 199 200 @Test testSaveSingleCaCertificateAlias()201 public void testSaveSingleCaCertificateAlias() { 202 final String alias = "single_alias 0"; 203 mEnterpriseConfig.setCaCertificateAliases(new String[] {alias}); 204 assertEquals(getCaCertField(), CA_CERT_PREFIX + alias); 205 } 206 207 @Test testLoadSingleCaCertificateAlias()208 public void testLoadSingleCaCertificateAlias() { 209 final String alias = "single_alias 1"; 210 setCaCertField(CA_CERT_PREFIX + alias); 211 String[] aliases = mEnterpriseConfig.getCaCertificateAliases(); 212 assertEquals(aliases.length, 1); 213 assertEquals(aliases[0], alias); 214 } 215 216 @Test testSaveMultipleCaCertificates()217 public void testSaveMultipleCaCertificates() { 218 final String alias0 = "single_alias 0"; 219 final String alias1 = "single_alias 1"; 220 mEnterpriseConfig.setCaCertificateAliases(new String[] {alias0, alias1}); 221 assertEquals(getCaCertField(), String.format("%s%s %s", 222 KEYSTORES_URI, 223 WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias0), 224 WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias1))); 225 } 226 227 @Test testSetStrictConservativePeerMode()228 public void testSetStrictConservativePeerMode() { 229 assertFalse(mEnterpriseConfig.getStrictConservativePeerMode()); 230 231 mEnterpriseConfig.setStrictConservativePeerMode(true); 232 233 assertTrue(mEnterpriseConfig.getStrictConservativePeerMode()); 234 } 235 236 @Test testLoadMultipleCaCertificates()237 public void testLoadMultipleCaCertificates() { 238 final String alias0 = "single_alias 0"; 239 final String alias1 = "single_alias 1"; 240 setCaCertField(String.format("%s%s %s", 241 KEYSTORES_URI, 242 WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias0), 243 WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias1))); 244 String[] aliases = mEnterpriseConfig.getCaCertificateAliases(); 245 assertEquals(aliases.length, 2); 246 assertEquals(aliases[0], alias0); 247 assertEquals(aliases[1], alias1); 248 } 249 getCaCertField()250 private String getCaCertField() { 251 return mEnterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY); 252 } 253 setCaCertField(String value)254 private void setCaCertField(String value) { 255 mEnterpriseConfig.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, value); 256 } 257 258 // Retrieves the value for a specific key supplied to wpa_supplicant. 259 private class SupplicantConfigExtractor implements WifiEnterpriseConfig.SupplicantSaver { 260 private String mValue = null; 261 private String mKey; 262 SupplicantConfigExtractor(String key)263 SupplicantConfigExtractor(String key) { 264 mKey = key; 265 } 266 267 @Override saveValue(String key, String value)268 public boolean saveValue(String key, String value) { 269 if (key.equals(mKey)) { 270 mValue = value; 271 } 272 return true; 273 } 274 getValue()275 public String getValue() { 276 return mValue; 277 } 278 } 279 getSupplicantEapMethod()280 private String getSupplicantEapMethod() { 281 SupplicantConfigExtractor entryExtractor = new SupplicantConfigExtractor( 282 WifiEnterpriseConfig.EAP_KEY); 283 mEnterpriseConfig.saveToSupplicant(entryExtractor); 284 return entryExtractor.getValue(); 285 } 286 getSupplicantPhase2Method()287 private String getSupplicantPhase2Method() { 288 SupplicantConfigExtractor entryExtractor = new SupplicantConfigExtractor( 289 WifiEnterpriseConfig.PHASE2_KEY); 290 mEnterpriseConfig.saveToSupplicant(entryExtractor); 291 return entryExtractor.getValue(); 292 } 293 294 /** Verifies the default value for EAP outer and inner methods */ 295 @Test eapInnerDefault()296 public void eapInnerDefault() { 297 assertEquals(null, getSupplicantEapMethod()); 298 assertEquals(null, getSupplicantPhase2Method()); 299 } 300 301 /** Verifies that the EAP inner method is reset when we switch to TLS */ 302 @Test eapPhase2MethodForTls()303 public void eapPhase2MethodForTls() { 304 // Initially select an EAP method that supports an phase2. 305 mEnterpriseConfig.setEapMethod(Eap.PEAP); 306 mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2); 307 assertEquals("PEAP", getSupplicantEapMethod()); 308 assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method()); 309 310 // Change the EAP method to another type which supports a phase2. 311 mEnterpriseConfig.setEapMethod(Eap.TTLS); 312 assertEquals("TTLS", getSupplicantEapMethod()); 313 assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method()); 314 315 // Change the EAP method to TLS which does not support a phase2. 316 mEnterpriseConfig.setEapMethod(Eap.TLS); 317 assertEquals(null, getSupplicantPhase2Method()); 318 } 319 320 /** Verfies that the EAP inner method is reset when we switch phase2 to NONE */ 321 @Test eapPhase2None()322 public void eapPhase2None() { 323 // Initially select an EAP method that supports an phase2. 324 mEnterpriseConfig.setEapMethod(Eap.PEAP); 325 mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2); 326 assertEquals("PEAP", getSupplicantEapMethod()); 327 assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method()); 328 329 // Change the phase2 method to NONE and ensure the value is cleared. 330 mEnterpriseConfig.setPhase2Method(Phase2.NONE); 331 assertEquals(null, getSupplicantPhase2Method()); 332 } 333 334 /** Verfies that the correct "autheap" parameter is supplied for TTLS/GTC. */ 335 @Test peapGtcToTtls()336 public void peapGtcToTtls() { 337 mEnterpriseConfig.setEapMethod(Eap.PEAP); 338 mEnterpriseConfig.setPhase2Method(Phase2.GTC); 339 assertEquals("PEAP", getSupplicantEapMethod()); 340 assertEquals("\"auth=GTC\"", getSupplicantPhase2Method()); 341 342 mEnterpriseConfig.setEapMethod(Eap.TTLS); 343 assertEquals("TTLS", getSupplicantEapMethod()); 344 assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method()); 345 } 346 347 /** Verfies that the correct "auth" parameter is supplied for PEAP/GTC. */ 348 @Test ttlsGtcToPeap()349 public void ttlsGtcToPeap() { 350 mEnterpriseConfig.setEapMethod(Eap.TTLS); 351 mEnterpriseConfig.setPhase2Method(Phase2.GTC); 352 assertEquals("TTLS", getSupplicantEapMethod()); 353 assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method()); 354 355 mEnterpriseConfig.setEapMethod(Eap.PEAP); 356 assertEquals("PEAP", getSupplicantEapMethod()); 357 assertEquals("\"auth=GTC\"", getSupplicantPhase2Method()); 358 } 359 360 /** Verfies PEAP/SIM, PEAP/AKA, PEAP/AKA'. */ 361 @Test peapSimAkaAkaPrime()362 public void peapSimAkaAkaPrime() { 363 mEnterpriseConfig.setEapMethod(Eap.PEAP); 364 mEnterpriseConfig.setPhase2Method(Phase2.SIM); 365 assertEquals("PEAP", getSupplicantEapMethod()); 366 assertEquals("\"auth=SIM\"", getSupplicantPhase2Method()); 367 368 mEnterpriseConfig.setPhase2Method(Phase2.AKA); 369 assertEquals("\"auth=AKA\"", getSupplicantPhase2Method()); 370 371 mEnterpriseConfig.setPhase2Method(Phase2.AKA_PRIME); 372 assertEquals("\"auth=AKA'\"", getSupplicantPhase2Method()); 373 } 374 375 /** 376 * Verifies that the copy constructor preseves both the masked password and inner method 377 * information. 378 */ 379 @Test copyConstructor()380 public void copyConstructor() { 381 WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); 382 enterpriseConfig.setPassword("*"); 383 enterpriseConfig.setEapMethod(Eap.TTLS); 384 enterpriseConfig.setPhase2Method(Phase2.GTC); 385 mEnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig); 386 assertEquals("TTLS", getSupplicantEapMethod()); 387 assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method()); 388 assertEquals("*", mEnterpriseConfig.getPassword()); 389 } 390 391 /** 392 * Verifies that the copy from external ignores masked passwords and preserves the 393 * inner method information. 394 */ 395 @Test copyFromExternal()396 public void copyFromExternal() { 397 WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); 398 enterpriseConfig.setPassword("*"); 399 enterpriseConfig.setEapMethod(Eap.TTLS); 400 enterpriseConfig.setPhase2Method(Phase2.GTC); 401 enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS); 402 mEnterpriseConfig = new WifiEnterpriseConfig(); 403 mEnterpriseConfig.copyFromExternal(enterpriseConfig, "*"); 404 assertEquals("TTLS", getSupplicantEapMethod()); 405 assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method()); 406 assertNotEquals("*", mEnterpriseConfig.getPassword()); 407 assertEquals(enterpriseConfig.getOcsp(), mEnterpriseConfig.getOcsp()); 408 } 409 410 /** Verfies that parceling a WifiEnterpriseConfig preseves method information. */ 411 @Test parcelConstructor()412 public void parcelConstructor() { 413 WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); 414 enterpriseConfig.setEapMethod(Eap.TTLS); 415 enterpriseConfig.setPhase2Method(Phase2.GTC); 416 Parcel parcel = Parcel.obtain(); 417 enterpriseConfig.writeToParcel(parcel, 0); 418 parcel.setDataPosition(0); // Allow parcel to be read from the beginning. 419 mEnterpriseConfig = WifiEnterpriseConfig.CREATOR.createFromParcel(parcel); 420 assertEquals("TTLS", getSupplicantEapMethod()); 421 assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method()); 422 } 423 424 /** 425 * Verifies that parceling a WifiEnterpriseConfig preserves the key 426 * and certificates information. 427 */ 428 @Test parcelConfigWithKeyAndCerts()429 public void parcelConfigWithKeyAndCerts() throws Exception { 430 WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); 431 PrivateKey clientKey = FakeKeys.RSA_KEY1; 432 X509Certificate clientCert = FakeKeys.CLIENT_CERT; 433 X509Certificate[] caCerts = new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}; 434 enterpriseConfig.setClientKeyEntry(clientKey, clientCert); 435 enterpriseConfig.setCaCertificates(caCerts); 436 Parcel parcel = Parcel.obtain(); 437 enterpriseConfig.writeToParcel(parcel, 0); 438 439 parcel.setDataPosition(0); // Allow parcel to be read from the beginning. 440 mEnterpriseConfig = WifiEnterpriseConfig.CREATOR.createFromParcel(parcel); 441 PrivateKey actualClientKey = mEnterpriseConfig.getClientPrivateKey(); 442 X509Certificate actualClientCert = mEnterpriseConfig.getClientCertificate(); 443 X509Certificate[] actualCaCerts = mEnterpriseConfig.getCaCertificates(); 444 445 /* Verify client private key. */ 446 assertNotNull(actualClientKey); 447 assertEquals(clientKey.getAlgorithm(), actualClientKey.getAlgorithm()); 448 assertArrayEquals(clientKey.getEncoded(), actualClientKey.getEncoded()); 449 450 /* Verify client certificate. */ 451 assertNotNull(actualClientCert); 452 assertArrayEquals(clientCert.getEncoded(), actualClientCert.getEncoded()); 453 454 /* Verify CA certificates. */ 455 assertNotNull(actualCaCerts); 456 assertEquals(caCerts.length, actualCaCerts.length); 457 for (int i = 0; i < caCerts.length; i++) { 458 assertNotNull(actualCaCerts[i]); 459 assertArrayEquals(caCerts[i].getEncoded(), actualCaCerts[i].getEncoded()); 460 } 461 } 462 463 /** Verifies proper operation of the getKeyId() method. */ 464 @Test getKeyId()465 public void getKeyId() { 466 assertEquals("NULL", mEnterpriseConfig.getKeyId(null)); 467 WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); 468 enterpriseConfig.setEapMethod(Eap.TTLS); 469 enterpriseConfig.setPhase2Method(Phase2.GTC); 470 assertEquals("TTLS_GTC", mEnterpriseConfig.getKeyId(enterpriseConfig)); 471 mEnterpriseConfig.setEapMethod(Eap.PEAP); 472 mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2); 473 assertEquals("PEAP_MSCHAPV2", mEnterpriseConfig.getKeyId(enterpriseConfig)); 474 } 475 476 /** Verifies that passwords are not displayed in toString. */ 477 @Test passwordNotInToString()478 public void passwordNotInToString() { 479 String password = "supersecret"; 480 mEnterpriseConfig.setPassword(password); 481 assertFalse(mEnterpriseConfig.toString().contains(password)); 482 } 483 484 /** Verifies that certificate ownership flag is set correctly */ 485 @Test testIsAppInstalledDeviceKeyAndCert()486 public void testIsAppInstalledDeviceKeyAndCert() { 487 // First make sure that app didn't install anything 488 assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert()); 489 assertFalse(mEnterpriseConfig.isAppInstalledCaCert()); 490 491 // Then app loads keys via the enterprise config API 492 PrivateKey clientKey = FakeKeys.RSA_KEY1; 493 X509Certificate cert0 = FakeKeys.CLIENT_CERT; 494 X509Certificate cert1 = FakeKeys.CA_CERT1; 495 X509Certificate[] clientChain = new X509Certificate[] {cert0, cert1}; 496 mEnterpriseConfig.setClientKeyEntryWithCertificateChain(clientKey, clientChain); 497 X509Certificate[] result = mEnterpriseConfig.getClientCertificateChain(); 498 assertEquals(result.length, 2); 499 assertTrue(result[0] == cert0 && result[1] == cert1); 500 assertTrue(mEnterpriseConfig.getClientCertificate() == cert0); 501 502 // Make sure it is the owner now 503 assertTrue(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert()); 504 assertFalse(mEnterpriseConfig.isAppInstalledCaCert()); 505 } 506 507 /** Verifies that certificate ownership flag is set correctly */ 508 @Test testIsAppInstalledCaCert()509 public void testIsAppInstalledCaCert() { 510 // First make sure that app didn't install anything 511 assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert()); 512 assertFalse(mEnterpriseConfig.isAppInstalledCaCert()); 513 514 // Then app loads CA cert via the enterprise config API 515 X509Certificate cert = FakeKeys.CA_CERT1; 516 mEnterpriseConfig.setCaCertificate(cert); 517 X509Certificate result = mEnterpriseConfig.getCaCertificate(); 518 assertTrue(result == cert); 519 520 // Make sure it is the owner now 521 assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert()); 522 assertTrue(mEnterpriseConfig.isAppInstalledCaCert()); 523 } 524 525 /** Verifies that certificate ownership flag is set correctly */ 526 @Test testIsAppInstalledCaCerts()527 public void testIsAppInstalledCaCerts() { 528 // First make sure that app didn't install anything 529 assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert()); 530 assertFalse(mEnterpriseConfig.isAppInstalledCaCert()); 531 532 // Then app loads CA cert via the enterprise config API 533 X509Certificate cert0 = FakeKeys.CA_CERT0; 534 X509Certificate cert1 = FakeKeys.CA_CERT1; 535 X509Certificate[] cert = new X509Certificate[] {cert0, cert1}; 536 537 mEnterpriseConfig.setCaCertificates(cert); 538 X509Certificate[] result = mEnterpriseConfig.getCaCertificates(); 539 assertEquals(result.length, 2); 540 assertTrue(result[0] == cert0 && result[1] == cert1); 541 // assertTrue(mEnterpriseConfig.getClientCertificate() == cert0); 542 543 // Make sure it is the owner now 544 assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert()); 545 assertTrue(mEnterpriseConfig.isAppInstalledCaCert()); 546 } 547 548 /** Verifies that OCSP value is set correctly. */ 549 @Test testOcspSetGet()550 public void testOcspSetGet() throws Exception { 551 WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); 552 553 enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_NONE); 554 assertEquals(WifiEnterpriseConfig.OCSP_NONE, enterpriseConfig.getOcsp()); 555 556 enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS); 557 assertEquals(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS, enterpriseConfig.getOcsp()); 558 559 enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS); 560 assertEquals(WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS, enterpriseConfig.getOcsp()); 561 562 enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS); 563 assertEquals(WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS, 564 enterpriseConfig.getOcsp()); 565 } 566 567 /** Verifies that an exception is thrown when invalid OCSP is set. */ 568 @Test testInvalidOcspValue()569 public void testInvalidOcspValue() { 570 WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); 571 try { 572 enterpriseConfig.setOcsp(-1); 573 fail("Should raise an IllegalArgumentException here."); 574 } catch (IllegalArgumentException e) { 575 // expected exception. 576 } 577 } 578 579 /** Verifies that the EAP inner method is reset when we switch to Unauth-TLS */ 580 @Test eapPhase2MethodForUnauthTls()581 public void eapPhase2MethodForUnauthTls() { 582 // Initially select an EAP method that supports an phase2. 583 mEnterpriseConfig.setEapMethod(Eap.PEAP); 584 mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2); 585 assertEquals("PEAP", getSupplicantEapMethod()); 586 assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method()); 587 588 // Change the EAP method to another type which supports a phase2. 589 mEnterpriseConfig.setEapMethod(Eap.TTLS); 590 assertEquals("TTLS", getSupplicantEapMethod()); 591 assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method()); 592 593 // Change the EAP method to Unauth-TLS which does not support a phase2. 594 mEnterpriseConfig.setEapMethod(Eap.UNAUTH_TLS); 595 assertEquals(null, getSupplicantPhase2Method()); 596 } 597 598 @Test testIsEnterpriseConfigServerCertNotEnabled()599 public void testIsEnterpriseConfigServerCertNotEnabled() { 600 WifiEnterpriseConfig baseConfig = new WifiEnterpriseConfig(); 601 baseConfig.setEapMethod(Eap.PEAP); 602 baseConfig.setPhase2Method(Phase2.MSCHAPV2); 603 assertTrue(baseConfig.isEapMethodServerCertUsed()); 604 assertFalse(baseConfig.isServerCertValidationEnabled()); 605 606 WifiEnterpriseConfig noMatchConfig = new WifiEnterpriseConfig(baseConfig); 607 noMatchConfig.setCaCertificate(FakeKeys.CA_CERT0); 608 // Missing match disables validation. 609 assertTrue(baseConfig.isEapMethodServerCertUsed()); 610 assertFalse(baseConfig.isServerCertValidationEnabled()); 611 612 WifiEnterpriseConfig noCaConfig = new WifiEnterpriseConfig(baseConfig); 613 noCaConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH); 614 // Missing CA certificate disables validation. 615 assertTrue(baseConfig.isEapMethodServerCertUsed()); 616 assertFalse(baseConfig.isServerCertValidationEnabled()); 617 618 WifiEnterpriseConfig noValidationConfig = new WifiEnterpriseConfig(); 619 noValidationConfig.setEapMethod(Eap.AKA); 620 assertFalse(noValidationConfig.isEapMethodServerCertUsed()); 621 } 622 623 @Test testIsEnterpriseConfigServerCertEnabledWithPeap()624 public void testIsEnterpriseConfigServerCertEnabledWithPeap() { 625 testIsEnterpriseConfigServerCertEnabled(Eap.PEAP); 626 } 627 628 @Test testIsEnterpriseConfigServerCertEnabledWithTls()629 public void testIsEnterpriseConfigServerCertEnabledWithTls() { 630 testIsEnterpriseConfigServerCertEnabled(Eap.TLS); 631 } 632 633 @Test testIsEnterpriseConfigServerCertEnabledWithTTLS()634 public void testIsEnterpriseConfigServerCertEnabledWithTTLS() { 635 testIsEnterpriseConfigServerCertEnabled(Eap.TTLS); 636 } 637 638 @Test testSetGetDecoratedIdentityPrefix()639 public void testSetGetDecoratedIdentityPrefix() { 640 assumeTrue(SdkLevel.isAtLeastS()); 641 WifiEnterpriseConfig config = new WifiEnterpriseConfig(); 642 643 assertNull(config.getDecoratedIdentityPrefix()); 644 config.setDecoratedIdentityPrefix(TEST_DECORATED_IDENTITY_PREFIX); 645 assertEquals(TEST_DECORATED_IDENTITY_PREFIX, config.getDecoratedIdentityPrefix()); 646 } 647 648 @Test testTrustOnFirstUse()649 public void testTrustOnFirstUse() { 650 WifiEnterpriseConfig config = new WifiEnterpriseConfig(); 651 652 assertFalse(config.isTrustOnFirstUseEnabled()); 653 config.enableTrustOnFirstUse(true); 654 assertTrue(config.isTrustOnFirstUseEnabled()); 655 config.enableTrustOnFirstUse(false); 656 assertFalse(config.isTrustOnFirstUseEnabled()); 657 } 658 659 @Test testHasCaCertificate()660 public void testHasCaCertificate() { 661 assumeTrue(SdkLevel.isAtLeastT()); 662 WifiEnterpriseConfig config = new WifiEnterpriseConfig(); 663 assertFalse(config.hasCaCertificate()); 664 config.setCaPath("/tmp/testCa.cert"); 665 assertTrue(config.hasCaCertificate()); 666 667 config = new WifiEnterpriseConfig(); 668 assertFalse(config.hasCaCertificate()); 669 config.setCaCertificate(FakeKeys.CA_CERT0); 670 assertTrue(config.hasCaCertificate()); 671 672 config = new WifiEnterpriseConfig(); 673 assertFalse(config.hasCaCertificate()); 674 config.setCaCertificateAliases(new String[] {"single_alias 0"}); 675 assertTrue(config.hasCaCertificate()); 676 } 677 678 @Test testUserApproveNoCaCert()679 public void testUserApproveNoCaCert() { 680 WifiEnterpriseConfig config = new WifiEnterpriseConfig(); 681 682 assertFalse(config.isUserApproveNoCaCert()); 683 config.setUserApproveNoCaCert(true); 684 assertTrue(config.isUserApproveNoCaCert()); 685 config.setUserApproveNoCaCert(false); 686 assertFalse(config.isUserApproveNoCaCert()); 687 } 688 689 /** 690 * Verify that the set decorated identity prefix doesn't accept a malformed input. 691 * 692 * @throws Exception 693 */ 694 @Test (expected = IllegalArgumentException.class) testSetDecoratedIdentityPrefixWithInvalidValue()695 public void testSetDecoratedIdentityPrefixWithInvalidValue() { 696 assumeTrue(SdkLevel.isAtLeastS()); 697 PasspointConfiguration config = new PasspointConfiguration(); 698 699 config.setDecoratedIdentityPrefix(TEST_DECORATED_IDENTITY_PREFIX.replace('!', 'a')); 700 } 701 702 @Test testSetGetSelectedRcoi()703 public void testSetGetSelectedRcoi() { 704 WifiEnterpriseConfig config = new WifiEnterpriseConfig(); 705 706 assertEquals(0, config.getSelectedRcoi()); 707 config.setSelectedRcoi(TEST_SELECTED_RCOI); 708 assertEquals(TEST_SELECTED_RCOI, config.getSelectedRcoi()); 709 } 710 testIsEnterpriseConfigServerCertEnabled(int eapMethod)711 private void testIsEnterpriseConfigServerCertEnabled(int eapMethod) { 712 WifiEnterpriseConfig configWithCertAndDomainSuffixMatch = createEnterpriseConfig(eapMethod, 713 Phase2.NONE, FakeKeys.CA_CERT0, null, TEST_DOMAIN_SUFFIX_MATCH, null); 714 assertTrue(configWithCertAndDomainSuffixMatch.isEapMethodServerCertUsed()); 715 assertTrue(configWithCertAndDomainSuffixMatch.isServerCertValidationEnabled()); 716 717 WifiEnterpriseConfig configWithCertAndAltSubjectMatch = createEnterpriseConfig(eapMethod, 718 Phase2.NONE, FakeKeys.CA_CERT0, null, null, TEST_ALT_SUBJECT_MATCH); 719 assertTrue(configWithCertAndAltSubjectMatch.isEapMethodServerCertUsed()); 720 assertTrue(configWithCertAndAltSubjectMatch.isServerCertValidationEnabled()); 721 722 WifiEnterpriseConfig configWithAliasAndDomainSuffixMatch = createEnterpriseConfig(eapMethod, 723 Phase2.NONE, null, new String[]{"alias1", "alisa2"}, TEST_DOMAIN_SUFFIX_MATCH, 724 null); 725 assertTrue(configWithAliasAndDomainSuffixMatch.isEapMethodServerCertUsed()); 726 assertTrue(configWithAliasAndDomainSuffixMatch.isServerCertValidationEnabled()); 727 728 WifiEnterpriseConfig configWithAliasAndAltSubjectMatch = createEnterpriseConfig(eapMethod, 729 Phase2.NONE, null, new String[]{"alias1", "alisa2"}, null, TEST_ALT_SUBJECT_MATCH); 730 assertTrue(configWithAliasAndAltSubjectMatch.isEapMethodServerCertUsed()); 731 assertTrue(configWithAliasAndAltSubjectMatch.isServerCertValidationEnabled()); 732 } 733 createEnterpriseConfig(int eapMethod, int phase2Method, X509Certificate caCertificate, String[] aliases, String domainSuffixMatch, String altSubjectMatch)734 private WifiEnterpriseConfig createEnterpriseConfig(int eapMethod, int phase2Method, 735 X509Certificate caCertificate, String[] aliases, String domainSuffixMatch, 736 String altSubjectMatch) { 737 WifiEnterpriseConfig config = new WifiEnterpriseConfig(); 738 config.setEapMethod(eapMethod); 739 config.setPhase2Method(phase2Method); 740 config.setCaCertificate(caCertificate); 741 config.setCaCertificateAliases(aliases); 742 config.setDomainSuffixMatch(domainSuffixMatch); 743 config.setAltSubjectMatch(altSubjectMatch); 744 return config; 745 } 746 747 /** 748 * Verify that setCaCertificate() raises IllegalArgumentException 749 * for a self-signed certificate. 750 * 751 * @throws IllegalArgumentException 752 */ 753 @Test (expected = IllegalArgumentException.class) testSetCaCertificateExceptionWithSelfSignedCert()754 public void testSetCaCertificateExceptionWithSelfSignedCert() throws Exception { 755 X509Certificate mockCert = mock(X509Certificate.class); 756 when(mockCert.getBasicConstraints()).thenReturn(-1); 757 758 mEnterpriseConfig.setCaCertificate(mockCert); 759 } 760 761 /** 762 * Verify that setCaCertificateForTrustOnFirstUse sunny case. 763 */ 764 @Test testSetCaCertificateForTrustOnFirstUseSuccess()765 public void testSetCaCertificateForTrustOnFirstUseSuccess() throws Exception { 766 X509Certificate mockCert = mock(X509Certificate.class); 767 when(mockCert.getBasicConstraints()).thenReturn(-1); 768 769 mEnterpriseConfig.enableTrustOnFirstUse(true); 770 771 mEnterpriseConfig.setCaCertificateForTrustOnFirstUse(mockCert); 772 assertEquals(mEnterpriseConfig.getCaCertificate(), mockCert); 773 } 774 775 /** 776 * Verify that setCaCertificateForTrustOnFirstUse() raises IllegalArgumentException 777 * when Trust on First Use is not enabled. 778 * 779 * @throws IllegalArgumentException 780 */ 781 @Test (expected = IllegalArgumentException.class) testSetCaCertificateForTrustOnFirstUseExceptionWithNoTofuEnabled()782 public void testSetCaCertificateForTrustOnFirstUseExceptionWithNoTofuEnabled() 783 throws Exception { 784 X509Certificate mockCert = mock(X509Certificate.class); 785 when(mockCert.getBasicConstraints()).thenReturn(-1); 786 787 mEnterpriseConfig.enableTrustOnFirstUse(false); 788 789 mEnterpriseConfig.setCaCertificateForTrustOnFirstUse(mockCert); 790 } 791 792 /** 793 * Verify setMinimumTlsVersion sunny cases. 794 */ 795 @Test testSetMinimumTlsVersionWithValidValues()796 public void testSetMinimumTlsVersionWithValidValues() throws Exception { 797 for (int i = WifiEnterpriseConfig.TLS_VERSION_MIN; 798 i <= WifiEnterpriseConfig.TLS_VERSION_MAX; i++) { 799 mEnterpriseConfig.setMinimumTlsVersion(i); 800 assertEquals(i, mEnterpriseConfig.getMinimumTlsVersion()); 801 } 802 } 803 804 /** 805 * Verify that setMinimumTlsVersion() raises IllegalArgumentException when 806 * an invalid TLS version is set. 807 * 808 * @throws IllegalArgumentException 809 */ 810 @Test (expected = IllegalArgumentException.class) testSetMinimumTlsVersionWithVersionLargerThanMaxVersion()811 public void testSetMinimumTlsVersionWithVersionLargerThanMaxVersion() throws Exception { 812 mEnterpriseConfig.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_VERSION_MAX + 1); 813 } 814 815 /** 816 * Verify that setMinimumTlsVersion() raises IllegalArgumentException when 817 * an invalid TLS version is set. 818 * 819 * @throws IllegalArgumentException 820 */ 821 @Test (expected = IllegalArgumentException.class) testSetMinimumTlsVersionWithVersionSmallerThanMinVersion()822 public void testSetMinimumTlsVersionWithVersionSmallerThanMinVersion() throws Exception { 823 mEnterpriseConfig.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_VERSION_MIN - 1); 824 } 825 826 /** 827 * Verify that fields with unsupported keys cannot be set or retrieved. 828 */ 829 @Test testCannotSetOrGetUnsupportedKeys()830 public void testCannotSetOrGetUnsupportedKeys() { 831 WifiEnterpriseConfig config = new WifiEnterpriseConfig(); 832 String password = "somePassword"; 833 config.setFieldValue(WifiEnterpriseConfig.PASSWORD_KEY, password); 834 assertEquals(password, config.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY)); 835 836 String invalidKey = "invalidKey"; 837 String invalidValue = "invalidValue"; 838 config.setFieldValue(invalidKey, invalidValue); 839 assertEquals("", config.getFieldValue(invalidKey)); 840 } 841 842 /** 843 * Construct a WifiEnterpriceConfig parcel using the provided fields map. 844 * Map is allowed to contain invalid keys. 845 */ constructParcelWithFieldsMap(Map<String, String> fieldsMap)846 private Parcel constructParcelWithFieldsMap(Map<String, String> fieldsMap) { 847 Parcel parcel = Parcel.obtain(); 848 Bundle bundle = new Bundle(); 849 for (Map.Entry<String, String> entry : fieldsMap.entrySet()) { 850 bundle.putString(entry.getKey(), entry.getValue()); 851 } 852 parcel.writeBundle(bundle); 853 854 // Use the default value for the remaining fields. 855 parcel.writeInt(Eap.NONE); 856 parcel.writeInt(Phase2.NONE); 857 parcel.writeInt(0); // numCaCertificates 858 parcel.writeString(null); // privateKey 859 parcel.writeInt(0); // numClientCertificates 860 parcel.writeString(""); // keyChainAlias 861 parcel.writeBoolean(false); // isAppInstalledDeviceKeyAndCert 862 parcel.writeBoolean(false); // isAppInstalledCaCert 863 parcel.writeInt(0); // OSCP 864 parcel.writeBoolean(false); // isTrustOnFirstUseEnabled 865 parcel.writeBoolean(false); // userApproveNoCaCert 866 parcel.writeInt(WifiEnterpriseConfig.TLS_V1_0); 867 return parcel; 868 } 869 870 /** 871 * Verify that unsupported keys are ignored during unparceling. 872 */ 873 @Test testUnsupportedKeysIgnoredDuringUnparceling()874 public void testUnsupportedKeysIgnoredDuringUnparceling() { 875 Map<String, String> fieldsMap = new HashMap<>(); 876 String password = "somePassword"; 877 fieldsMap.put(WifiEnterpriseConfig.PASSWORD_KEY, password); 878 879 String invalidKey = "invalidKey"; 880 String invalidValue = "invalidValue"; 881 fieldsMap.put(invalidKey, invalidValue); 882 883 // Invalid field should be ignored during unparceling. 884 Parcel parcel = constructParcelWithFieldsMap(fieldsMap); 885 parcel.setDataPosition(0); 886 WifiEnterpriseConfig config = WifiEnterpriseConfig.CREATOR.createFromParcel(parcel); 887 assertEquals(password, config.getPassword()); 888 assertEquals("", config.getFieldValue(invalidKey)); 889 } 890 891 /** 892 * Verify that fields with invalid field lengths cannot be set or retrieved. 893 */ 894 @Test testCannotSetOrGetFieldsWithInvalidLength()895 public void testCannotSetOrGetFieldsWithInvalidLength() { 896 WifiEnterpriseConfig config = new WifiEnterpriseConfig(); 897 String password = "somePassword"; 898 config.setFieldValue(WifiEnterpriseConfig.PASSWORD_KEY, password); 899 assertEquals(password, config.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY)); 900 901 // Value of OPP_KEY_CACHING is expected to have a length of 1. 902 String invalidValue = "invalidValue"; 903 config.setFieldValue(WifiEnterpriseConfig.OPP_KEY_CACHING, invalidValue); 904 assertEquals("", config.getFieldValue(WifiEnterpriseConfig.OPP_KEY_CACHING)); 905 } 906 907 /** 908 * Verify that field values with invalid lengths are ignored during unparceling. 909 */ 910 @Test testFieldsWithInvalidLengthIgnoredDuringUnparceling()911 public void testFieldsWithInvalidLengthIgnoredDuringUnparceling() { 912 Map<String, String> fieldsMap = new HashMap<>(); 913 String password = "somePassword"; 914 fieldsMap.put(WifiEnterpriseConfig.PASSWORD_KEY, password); 915 916 // Value of OPP_KEY_CACHING is expected to have a length of 1. 917 String invalidValue = "invalidValue"; 918 fieldsMap.put(WifiEnterpriseConfig.OPP_KEY_CACHING, invalidValue); 919 920 // Invalid field should be ignored during unparceling. 921 Parcel parcel = constructParcelWithFieldsMap(fieldsMap); 922 parcel.setDataPosition(0); 923 WifiEnterpriseConfig config = WifiEnterpriseConfig.CREATOR.createFromParcel(parcel); 924 assertEquals(password, config.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY)); 925 assertEquals("", config.getFieldValue(WifiEnterpriseConfig.OPP_KEY_CACHING)); 926 } 927 } 928