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 com.android.server.wifi.hotspot2; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertTrue; 22 import static org.mockito.Mockito.verify; 23 import static org.mockito.Mockito.when; 24 import static org.mockito.MockitoAnnotations.initMocks; 25 26 import android.net.wifi.EAPConstants; 27 import android.net.wifi.WifiConfiguration; 28 import android.net.wifi.WifiEnterpriseConfig; 29 import android.net.wifi.hotspot2.PasspointConfiguration; 30 import android.net.wifi.hotspot2.pps.Credential; 31 import android.net.wifi.hotspot2.pps.HomeSp; 32 import android.test.suitebuilder.annotation.SmallTest; 33 import android.util.Base64; 34 35 import com.android.server.wifi.FakeKeys; 36 import com.android.server.wifi.IMSIParameter; 37 import com.android.server.wifi.SIMAccessor; 38 import com.android.server.wifi.WifiKeyStore; 39 import com.android.server.wifi.hotspot2.anqp.ANQPElement; 40 import com.android.server.wifi.hotspot2.anqp.CellularNetwork; 41 import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType; 42 import com.android.server.wifi.hotspot2.anqp.DomainNameElement; 43 import com.android.server.wifi.hotspot2.anqp.NAIRealmData; 44 import com.android.server.wifi.hotspot2.anqp.NAIRealmElement; 45 import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement; 46 import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement; 47 import com.android.server.wifi.hotspot2.anqp.eap.AuthParam; 48 import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod; 49 import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth; 50 51 import org.junit.Before; 52 import org.junit.Test; 53 import org.mockito.Mock; 54 55 import java.nio.charset.StandardCharsets; 56 import java.security.MessageDigest; 57 import java.security.cert.X509Certificate; 58 import java.util.Arrays; 59 import java.util.HashMap; 60 import java.util.HashSet; 61 import java.util.Map; 62 import java.util.Set; 63 64 /** 65 * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointProvider}. 66 */ 67 @SmallTest 68 public class PasspointProviderTest { 69 private static final long PROVIDER_ID = 12L; 70 private static final int CREATOR_UID = 1234; 71 private static final String CA_CERTIFICATE_NAME = "CACERT_HS2_12"; 72 private static final String CLIENT_CERTIFICATE_NAME = "USRCERT_HS2_12"; 73 private static final String CLIENT_PRIVATE_KEY_NAME = "USRPKEY_HS2_12"; 74 private static final String CA_CERTIFICATE_ALIAS = "HS2_12"; 75 private static final String CLIENT_CERTIFICATE_ALIAS = "HS2_12"; 76 private static final String CLIENT_PRIVATE_KEY_ALIAS = "HS2_12"; 77 78 @Mock WifiKeyStore mKeyStore; 79 @Mock SIMAccessor mSimAccessor; 80 PasspointProvider mProvider; 81 82 /** Sets up test. */ 83 @Before 84 public void setUp() throws Exception { 85 initMocks(this); 86 } 87 88 /** 89 * Helper function for creating a provider instance for testing. 90 * 91 * @param config The configuration associated with the provider 92 * @return {@link com.android.server.wifi.hotspot2.PasspointProvider} 93 */ 94 private PasspointProvider createProvider(PasspointConfiguration config) { 95 return new PasspointProvider(config, mKeyStore, mSimAccessor, PROVIDER_ID, CREATOR_UID); 96 } 97 98 /** 99 * Verify that the configuration associated with the provider is the same or not the same 100 * as the expected configuration. 101 * 102 * @param expectedConfig The expected configuration 103 * @param equals Flag indicating equality or inequality check 104 */ 105 private void verifyInstalledConfig(PasspointConfiguration expectedConfig, boolean equals) { 106 PasspointConfiguration actualConfig = mProvider.getConfig(); 107 if (equals) { 108 assertTrue(actualConfig.equals(expectedConfig)); 109 } else { 110 assertFalse(actualConfig.equals(expectedConfig)); 111 } 112 } 113 114 /** 115 * Helper function for creating a Domain Name ANQP element. 116 * 117 * @param domains List of domain names 118 * @return {@link DomainNameElement} 119 */ 120 private DomainNameElement createDomainNameElement(String[] domains) { 121 return new DomainNameElement(Arrays.asList(domains)); 122 } 123 124 /** 125 * Helper function for creating a NAI Realm ANQP element. 126 * 127 * @param realm The realm of the network 128 * @param eapMethodID EAP Method ID 129 * @param authParam Authentication parameter 130 * @return {@link NAIRealmElement} 131 */ 132 private NAIRealmElement createNAIRealmElement(String realm, int eapMethodID, 133 AuthParam authParam) { 134 Map<Integer, Set<AuthParam>> authParamMap = new HashMap<>(); 135 if (authParam != null) { 136 Set<AuthParam> authSet = new HashSet<>(); 137 authSet.add(authParam); 138 authParamMap.put(authParam.getAuthTypeID(), authSet); 139 } 140 EAPMethod eapMethod = new EAPMethod(eapMethodID, authParamMap); 141 NAIRealmData realmData = new NAIRealmData(Arrays.asList(new String[] {realm}), 142 Arrays.asList(new EAPMethod[] {eapMethod})); 143 return new NAIRealmElement(Arrays.asList(new NAIRealmData[] {realmData})); 144 } 145 146 /** 147 * Helper function for creating a Roaming Consortium ANQP element. 148 * 149 * @param rcOIs Roaming consortium OIs 150 * @return {@link RoamingConsortiumElement} 151 */ 152 private RoamingConsortiumElement createRoamingConsortiumElement(Long[] rcOIs) { 153 return new RoamingConsortiumElement(Arrays.asList(rcOIs)); 154 } 155 156 /** 157 * Helper function for creating a 3GPP Network ANQP element. 158 * 159 * @param imsiList List of IMSI to be included in a 3GPP Network 160 * @return {@link ThreeGPPNetworkElement} 161 */ 162 private ThreeGPPNetworkElement createThreeGPPNetworkElement(String[] imsiList) { 163 CellularNetwork network = new CellularNetwork(Arrays.asList(imsiList)); 164 return new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network})); 165 } 166 167 /** 168 * Verify that modification to the configuration used for creating PasspointProvider 169 * will not change the configuration stored inside the PasspointProvider. 170 * 171 * @throws Exception 172 */ 173 @Test 174 public void verifyModifyOriginalConfig() throws Exception { 175 // Create a dummy PasspointConfiguration. 176 PasspointConfiguration config = new PasspointConfiguration(); 177 HomeSp homeSp = new HomeSp(); 178 homeSp.setFqdn("test1"); 179 config.setHomeSp(homeSp); 180 Credential credential = new Credential(); 181 credential.setUserCredential(new Credential.UserCredential()); 182 config.setCredential(credential); 183 mProvider = createProvider(config); 184 verifyInstalledConfig(config, true); 185 186 // Modify the original configuration, the configuration maintained by the provider 187 // should be unchanged. 188 config.getHomeSp().setFqdn("test2"); 189 verifyInstalledConfig(config, false); 190 } 191 192 /** 193 * Verify that modification to the configuration retrieved from the PasspointProvider 194 * will not change the configuration stored inside the PasspointProvider. 195 * 196 * @throws Exception 197 */ 198 @Test 199 public void verifyModifyRetrievedConfig() throws Exception { 200 // Create a dummy PasspointConfiguration. 201 PasspointConfiguration config = new PasspointConfiguration(); 202 HomeSp homeSp = new HomeSp(); 203 homeSp.setFqdn("test1"); 204 config.setHomeSp(homeSp); 205 Credential credential = new Credential(); 206 credential.setUserCredential(new Credential.UserCredential()); 207 config.setCredential(credential); 208 mProvider = createProvider(config); 209 verifyInstalledConfig(config, true); 210 211 // Modify the retrieved configuration, verify the configuration maintained by the 212 // provider should be unchanged. 213 PasspointConfiguration retrievedConfig = mProvider.getConfig(); 214 retrievedConfig.getHomeSp().setFqdn("test2"); 215 verifyInstalledConfig(retrievedConfig, false); 216 } 217 218 /** 219 * Verify a successful installation of certificates and key. 220 * 221 * @throws Exception 222 */ 223 @Test 224 public void installCertsAndKeysSuccess() throws Exception { 225 // Create a dummy configuration with certificate credential. 226 PasspointConfiguration config = new PasspointConfiguration(); 227 Credential credential = new Credential(); 228 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 229 certCredential.setCertSha256Fingerprint( 230 MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded())); 231 credential.setCertCredential(certCredential); 232 credential.setCaCertificate(FakeKeys.CA_CERT0); 233 credential.setClientPrivateKey(FakeKeys.RSA_KEY1); 234 credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT}); 235 config.setCredential(credential); 236 mProvider = createProvider(config); 237 238 // Install client certificate and key to the keystore successfully. 239 when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_NAME, FakeKeys.CA_CERT0)) 240 .thenReturn(true); 241 when(mKeyStore.putKeyInKeyStore(CLIENT_PRIVATE_KEY_NAME, FakeKeys.RSA_KEY1)) 242 .thenReturn(true); 243 when(mKeyStore.putCertInKeyStore(CLIENT_CERTIFICATE_NAME, FakeKeys.CLIENT_CERT)) 244 .thenReturn(true); 245 assertTrue(mProvider.installCertsAndKeys()); 246 247 // Verify client certificate and key in the configuration gets cleared and aliases 248 // are set correctly. 249 PasspointConfiguration curConfig = mProvider.getConfig(); 250 assertTrue(curConfig.getCredential().getCaCertificate() == null); 251 assertTrue(curConfig.getCredential().getClientPrivateKey() == null); 252 assertTrue(curConfig.getCredential().getClientCertificateChain() == null); 253 assertTrue(mProvider.getCaCertificateAlias().equals(CA_CERTIFICATE_ALIAS)); 254 assertTrue(mProvider.getClientPrivateKeyAlias().equals(CLIENT_PRIVATE_KEY_ALIAS)); 255 assertTrue(mProvider.getClientCertificateAlias().equals(CLIENT_CERTIFICATE_ALIAS)); 256 } 257 258 /** 259 * Verify a failure installation of certificates and key. 260 * 261 * @throws Exception 262 */ 263 @Test 264 public void installCertsAndKeysFailure() throws Exception { 265 // Create a dummy configuration with certificate credential. 266 PasspointConfiguration config = new PasspointConfiguration(); 267 Credential credential = new Credential(); 268 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 269 certCredential.setCertSha256Fingerprint( 270 MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded())); 271 credential.setCertCredential(certCredential); 272 credential.setCaCertificate(FakeKeys.CA_CERT0); 273 credential.setClientPrivateKey(FakeKeys.RSA_KEY1); 274 credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT}); 275 config.setCredential(credential); 276 mProvider = createProvider(config); 277 278 // Failed to install client certificate to the keystore. 279 when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_NAME, FakeKeys.CA_CERT0)) 280 .thenReturn(true); 281 when(mKeyStore.putKeyInKeyStore(CLIENT_PRIVATE_KEY_NAME, FakeKeys.RSA_KEY1)) 282 .thenReturn(true); 283 when(mKeyStore.putCertInKeyStore(CLIENT_CERTIFICATE_NAME, FakeKeys.CLIENT_CERT)) 284 .thenReturn(false); 285 assertFalse(mProvider.installCertsAndKeys()); 286 287 // Verify certificates and key in the configuration are not cleared and aliases 288 // are not set. 289 PasspointConfiguration curConfig = mProvider.getConfig(); 290 assertTrue(curConfig.getCredential().getCaCertificate() != null); 291 assertTrue(curConfig.getCredential().getClientCertificateChain() != null); 292 assertTrue(curConfig.getCredential().getClientPrivateKey() != null); 293 assertTrue(mProvider.getCaCertificateAlias() == null); 294 assertTrue(mProvider.getClientPrivateKeyAlias() == null); 295 assertTrue(mProvider.getClientCertificateAlias() == null); 296 } 297 298 /** 299 * Verify a successful uninstallation of certificates and key. 300 */ 301 @Test 302 public void uninstallCertsAndKeys() throws Exception { 303 // Create a dummy configuration with certificate credential. 304 PasspointConfiguration config = new PasspointConfiguration(); 305 Credential credential = new Credential(); 306 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 307 certCredential.setCertSha256Fingerprint( 308 MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded())); 309 credential.setCertCredential(certCredential); 310 credential.setCaCertificate(FakeKeys.CA_CERT0); 311 credential.setClientPrivateKey(FakeKeys.RSA_KEY1); 312 credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT}); 313 config.setCredential(credential); 314 mProvider = createProvider(config); 315 316 // Install client certificate and key to the keystore successfully. 317 when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_NAME, FakeKeys.CA_CERT0)) 318 .thenReturn(true); 319 when(mKeyStore.putKeyInKeyStore(CLIENT_PRIVATE_KEY_NAME, FakeKeys.RSA_KEY1)) 320 .thenReturn(true); 321 when(mKeyStore.putCertInKeyStore(CLIENT_CERTIFICATE_NAME, FakeKeys.CLIENT_CERT)) 322 .thenReturn(true); 323 assertTrue(mProvider.installCertsAndKeys()); 324 assertTrue(mProvider.getCaCertificateAlias().equals(CA_CERTIFICATE_ALIAS)); 325 assertTrue(mProvider.getClientPrivateKeyAlias().equals(CLIENT_PRIVATE_KEY_ALIAS)); 326 assertTrue(mProvider.getClientCertificateAlias().equals(CLIENT_CERTIFICATE_ALIAS)); 327 328 // Uninstall certificates and key from the keystore. 329 mProvider.uninstallCertsAndKeys(); 330 verify(mKeyStore).removeEntryFromKeyStore(CA_CERTIFICATE_NAME); 331 verify(mKeyStore).removeEntryFromKeyStore(CLIENT_CERTIFICATE_NAME); 332 verify(mKeyStore).removeEntryFromKeyStore(CLIENT_PRIVATE_KEY_NAME); 333 assertTrue(mProvider.getCaCertificateAlias() == null); 334 assertTrue(mProvider.getClientPrivateKeyAlias() == null); 335 assertTrue(mProvider.getClientCertificateAlias() == null); 336 } 337 338 /** 339 * Verify that a provider is a home provider when its FQDN matches a domain name in the 340 * Domain Name ANQP element and no NAI realm is provided. 341 * 342 * @throws Exception 343 */ 344 @Test 345 public void matchFQDNWithoutNAIRealm() throws Exception { 346 String testDomain = "test.com"; 347 348 // Setup test provider. 349 PasspointConfiguration config = new PasspointConfiguration(); 350 HomeSp homeSp = new HomeSp(); 351 homeSp.setFqdn(testDomain); 352 config.setHomeSp(homeSp); 353 Credential credential = new Credential(); 354 Credential.UserCredential userCredential = new Credential.UserCredential(); 355 userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2); 356 credential.setUserCredential(userCredential); 357 config.setCredential(credential); 358 mProvider = createProvider(config); 359 360 // Setup ANQP elements. 361 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 362 anqpElementMap.put(ANQPElementType.ANQPDomName, 363 createDomainNameElement(new String[] {testDomain})); 364 365 assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap)); 366 } 367 368 /** 369 * Verify that a provider is a home provider when its FQDN matches a domain name in the 370 * Domain Name ANQP element and the provider's credential matches the NAI realm provided. 371 * 372 * @throws Exception 373 */ 374 @Test 375 public void matchFQDNWithNAIRealmMatch() throws Exception { 376 String testDomain = "test.com"; 377 String testRealm = "realm.com"; 378 379 // Setup test provider. 380 PasspointConfiguration config = new PasspointConfiguration(); 381 HomeSp homeSp = new HomeSp(); 382 homeSp.setFqdn(testDomain); 383 config.setHomeSp(homeSp); 384 Credential credential = new Credential(); 385 credential.setRealm(testRealm); 386 Credential.UserCredential userCredential = new Credential.UserCredential(); 387 userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2); 388 credential.setUserCredential(userCredential); 389 config.setCredential(credential); 390 mProvider = createProvider(config); 391 392 // Setup Domain Name ANQP element. 393 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 394 anqpElementMap.put(ANQPElementType.ANQPDomName, 395 createDomainNameElement(new String[] {testDomain})); 396 anqpElementMap.put(ANQPElementType.ANQPNAIRealm, 397 createNAIRealmElement(testRealm, EAPConstants.EAP_TTLS, 398 new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2))); 399 400 assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap)); 401 } 402 403 /** 404 * Verify that there is no match when the provider's FQDN matches a domain name in the 405 * Domain Name ANQP element but the provider's credential doesn't match the authentication 406 * method provided in the NAI realm. 407 * 408 * @throws Exception 409 */ 410 @Test 411 public void matchFQDNWithNAIRealmMismatch() throws Exception { 412 String testDomain = "test.com"; 413 String testRealm = "realm.com"; 414 415 // Setup test provider. 416 PasspointConfiguration config = new PasspointConfiguration(); 417 HomeSp homeSp = new HomeSp(); 418 homeSp.setFqdn(testDomain); 419 config.setHomeSp(homeSp); 420 Credential credential = new Credential(); 421 credential.setRealm(testRealm); 422 Credential.UserCredential userCredential = new Credential.UserCredential(); 423 userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2); 424 credential.setUserCredential(userCredential); 425 config.setCredential(credential); 426 mProvider = createProvider(config); 427 428 // Setup Domain Name ANQP element. 429 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 430 anqpElementMap.put(ANQPElementType.ANQPDomName, 431 createDomainNameElement(new String[] {testDomain})); 432 anqpElementMap.put(ANQPElementType.ANQPNAIRealm, 433 createNAIRealmElement(testRealm, EAPConstants.EAP_TLS, null)); 434 435 assertEquals(PasspointMatch.None, mProvider.match(anqpElementMap)); 436 } 437 438 /** 439 * Verify that a provider is a home provider when its SIM credential matches an 3GPP network 440 * domain name in the Domain Name ANQP element. 441 * 442 * @throws Exception 443 */ 444 @Test 445 public void match3GPPNetworkDomainName() throws Exception { 446 String testImsi = "1234567890"; 447 448 // Setup test provider. 449 PasspointConfiguration config = new PasspointConfiguration(); 450 config.setHomeSp(new HomeSp()); 451 Credential credential = new Credential(); 452 Credential.SimCredential simCredential = new Credential.SimCredential(); 453 simCredential.setImsi(testImsi); 454 credential.setSimCredential(simCredential); 455 config.setCredential(credential); 456 when(mSimAccessor.getMatchingImsis(new IMSIParameter(testImsi, false))) 457 .thenReturn(Arrays.asList(new String[] {testImsi})); 458 mProvider = createProvider(config); 459 460 // Setup Domain Name ANQP element. 461 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 462 anqpElementMap.put(ANQPElementType.ANQPDomName, 463 createDomainNameElement(new String[] {"wlan.mnc456.mcc123.3gppnetwork.org"})); 464 465 assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap)); 466 } 467 468 /** 469 * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI 470 * in the roaming consortium ANQP element. 471 * 472 * @throws Exception 473 */ 474 @Test 475 public void matchRoamingConsortium() throws Exception { 476 long[] providerRCOIs = new long[] {0x1234L, 0x2345L}; 477 Long[] anqpRCOIs = new Long[] {0x1234L, 0x2133L}; 478 479 // Setup test provider. 480 PasspointConfiguration config = new PasspointConfiguration(); 481 HomeSp homeSp = new HomeSp(); 482 homeSp.setRoamingConsortiumOis(providerRCOIs); 483 config.setHomeSp(homeSp); 484 Credential credential = new Credential(); 485 Credential.UserCredential userCredential = new Credential.UserCredential(); 486 userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2); 487 credential.setUserCredential(userCredential); 488 config.setCredential(credential); 489 mProvider = createProvider(config); 490 491 // Setup Roaming Consortium ANQP element. 492 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 493 anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, 494 createRoamingConsortiumElement(anqpRCOIs)); 495 496 assertEquals(PasspointMatch.RoamingProvider, mProvider.match(anqpElementMap)); 497 } 498 499 /** 500 * Verify that a provider is a roaming provider when the provider's IMSI parameter and an 501 * IMSI from the SIM card matches a MCC-MNC in the 3GPP Network ANQP element. 502 * 503 * @throws Exception 504 */ 505 @Test 506 public void matchThreeGPPNetwork() throws Exception { 507 String testImsi = "1234567890"; 508 509 // Setup test provider. 510 PasspointConfiguration config = new PasspointConfiguration(); 511 config.setHomeSp(new HomeSp()); 512 Credential credential = new Credential(); 513 Credential.SimCredential simCredential = new Credential.SimCredential(); 514 simCredential.setImsi(testImsi); 515 credential.setSimCredential(simCredential); 516 config.setCredential(credential); 517 when(mSimAccessor.getMatchingImsis(new IMSIParameter(testImsi, false))) 518 .thenReturn(Arrays.asList(new String[] {testImsi})); 519 mProvider = createProvider(config); 520 521 // Setup 3GPP Network ANQP element. 522 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 523 anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, 524 createThreeGPPNetworkElement(new String[] {"123456"})); 525 526 assertEquals(PasspointMatch.RoamingProvider, mProvider.match(anqpElementMap)); 527 } 528 529 /** 530 * Verify that a provider is a roaming provider when its credential matches a NAI realm in 531 * the NAI Realm ANQP element. 532 * 533 * @throws Exception 534 */ 535 @Test 536 public void matchNAIRealm() throws Exception { 537 String testRealm = "realm.com"; 538 539 // Setup test provider. 540 PasspointConfiguration config = new PasspointConfiguration(); 541 config.setHomeSp(new HomeSp()); 542 Credential credential = new Credential(); 543 credential.setRealm(testRealm); 544 Credential.UserCredential userCredential = new Credential.UserCredential(); 545 userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2); 546 credential.setUserCredential(userCredential); 547 config.setCredential(credential); 548 mProvider = createProvider(config); 549 550 // Setup NAI Realm ANQP element. 551 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 552 anqpElementMap.put(ANQPElementType.ANQPNAIRealm, 553 createNAIRealmElement(testRealm, EAPConstants.EAP_TTLS, 554 new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2))); 555 556 assertEquals(PasspointMatch.RoamingProvider, mProvider.match(anqpElementMap)); 557 } 558 559 /** 560 * Verify that a provider is a home provider when its FQDN, roaming consortium OI, and 561 * IMSI all matched against the ANQP elements, since we prefer matching home provider over 562 * roaming provider. 563 * 564 * @throws Exception 565 */ 566 @Test 567 public void matchHomeOverRoamingProvider() throws Exception { 568 // Setup test data. 569 String testDomain = "test.com"; 570 String testImsi = "1234567890"; 571 long[] providerRCOIs = new long[] {0x1234L, 0x2345L}; 572 Long[] anqpRCOIs = new Long[] {0x1234L, 0x2133L}; 573 574 // Setup test provider. 575 PasspointConfiguration config = new PasspointConfiguration(); 576 HomeSp homeSp = new HomeSp(); 577 homeSp.setFqdn(testDomain); 578 homeSp.setRoamingConsortiumOis(providerRCOIs); 579 config.setHomeSp(homeSp); 580 Credential credential = new Credential(); 581 Credential.SimCredential simCredential = new Credential.SimCredential(); 582 simCredential.setImsi(testImsi); 583 credential.setSimCredential(simCredential); 584 config.setCredential(credential); 585 when(mSimAccessor.getMatchingImsis(new IMSIParameter(testImsi, false))) 586 .thenReturn(Arrays.asList(new String[] {testImsi})); 587 mProvider = createProvider(config); 588 589 // Setup ANQP elements. 590 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 591 anqpElementMap.put(ANQPElementType.ANQPDomName, 592 createDomainNameElement(new String[] {testDomain})); 593 anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium, 594 createRoamingConsortiumElement(anqpRCOIs)); 595 anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork, 596 createThreeGPPNetworkElement(new String[] {"123456"})); 597 598 assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap)); 599 } 600 601 /** 602 * Verify that an expected WifiConfiguration will be returned for a Passpoint provider 603 * with an user credential. 604 * 605 * @throws Exception 606 */ 607 @Test 608 public void getWifiConfigWithUserCredential() throws Exception { 609 // Test data. 610 String fqdn = "test.com"; 611 String friendlyName = "Friendly Name"; 612 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 613 String realm = "realm.com"; 614 String username = "username"; 615 String password = "password"; 616 byte[] base64EncodedPw = 617 Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); 618 String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8); 619 620 // Create provider. 621 PasspointConfiguration config = new PasspointConfiguration(); 622 HomeSp homeSp = new HomeSp(); 623 homeSp.setFqdn(fqdn); 624 homeSp.setFriendlyName(friendlyName); 625 homeSp.setRoamingConsortiumOis(rcOIs); 626 config.setHomeSp(homeSp); 627 Credential credential = new Credential(); 628 credential.setRealm(realm); 629 Credential.UserCredential userCredential = new Credential.UserCredential(); 630 userCredential.setUsername(username); 631 userCredential.setPassword(encodedPasswordStr); 632 userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2); 633 credential.setUserCredential(userCredential); 634 credential.setCaCertificate(FakeKeys.CA_CERT0); 635 config.setCredential(credential); 636 mProvider = createProvider(config); 637 638 // Install certificate. 639 when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_NAME, FakeKeys.CA_CERT0)) 640 .thenReturn(true); 641 assertTrue(mProvider.installCertsAndKeys()); 642 643 // Retrieve the WifiConfiguration associated with the provider, and verify the content of 644 // the configuration. Need to verify field by field since WifiConfiguration doesn't 645 // override equals() function. 646 WifiConfiguration wifiConfig = mProvider.getWifiConfig(); 647 WifiEnterpriseConfig wifiEnterpriseConfig = wifiConfig.enterpriseConfig; 648 assertEquals(fqdn, wifiConfig.FQDN); 649 assertEquals(friendlyName, wifiConfig.providerFriendlyName); 650 assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds)); 651 assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)); 652 assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)); 653 assertEquals(realm, wifiEnterpriseConfig.getRealm()); 654 assertEquals(fqdn, wifiEnterpriseConfig.getDomainSuffixMatch()); 655 assertEquals("anonymous@" + realm, wifiEnterpriseConfig.getAnonymousIdentity()); 656 assertEquals(WifiEnterpriseConfig.Eap.TTLS, wifiEnterpriseConfig.getEapMethod()); 657 assertEquals(WifiEnterpriseConfig.Phase2.MSCHAPV2, wifiEnterpriseConfig.getPhase2Method()); 658 assertEquals(username, wifiEnterpriseConfig.getIdentity()); 659 assertEquals(password, wifiEnterpriseConfig.getPassword()); 660 assertEquals(CA_CERTIFICATE_ALIAS, wifiEnterpriseConfig.getCaCertificateAlias()); 661 } 662 663 /** 664 * Verify that an expected WifiConfiguration will be returned for a Passpoint provider 665 * with a certificate credential. 666 * 667 * @throws Exception 668 */ 669 @Test 670 public void getWifiConfigWithCertCredential() throws Exception { 671 // Test data. 672 String fqdn = "test.com"; 673 String friendlyName = "Friendly Name"; 674 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 675 String realm = "realm.com"; 676 677 // Create provider. 678 PasspointConfiguration config = new PasspointConfiguration(); 679 HomeSp homeSp = new HomeSp(); 680 homeSp.setFqdn(fqdn); 681 homeSp.setFriendlyName(friendlyName); 682 homeSp.setRoamingConsortiumOis(rcOIs); 683 config.setHomeSp(homeSp); 684 Credential credential = new Credential(); 685 credential.setRealm(realm); 686 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 687 certCredential.setCertSha256Fingerprint( 688 MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded())); 689 credential.setCertCredential(certCredential); 690 credential.setCaCertificate(FakeKeys.CA_CERT0); 691 credential.setClientPrivateKey(FakeKeys.RSA_KEY1); 692 credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT}); 693 config.setCredential(credential); 694 mProvider = createProvider(config); 695 696 // Install certificate. 697 when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_NAME, FakeKeys.CA_CERT0)) 698 .thenReturn(true); 699 when(mKeyStore.putKeyInKeyStore(CLIENT_PRIVATE_KEY_NAME, FakeKeys.RSA_KEY1)) 700 .thenReturn(true); 701 when(mKeyStore.putCertInKeyStore(CLIENT_CERTIFICATE_NAME, FakeKeys.CLIENT_CERT)) 702 .thenReturn(true); 703 assertTrue(mProvider.installCertsAndKeys()); 704 705 // Retrieve the WifiConfiguration associated with the provider, and verify the content of 706 // the configuration. Need to verify field by field since WifiConfiguration doesn't 707 // override equals() function. 708 WifiConfiguration wifiConfig = mProvider.getWifiConfig(); 709 WifiEnterpriseConfig wifiEnterpriseConfig = wifiConfig.enterpriseConfig; 710 assertEquals(fqdn, wifiConfig.FQDN); 711 assertEquals(friendlyName, wifiConfig.providerFriendlyName); 712 assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds)); 713 assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)); 714 assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)); 715 assertEquals(realm, wifiEnterpriseConfig.getRealm()); 716 assertEquals(fqdn, wifiEnterpriseConfig.getDomainSuffixMatch()); 717 assertEquals("anonymous@" + realm, wifiEnterpriseConfig.getAnonymousIdentity()); 718 assertEquals(WifiEnterpriseConfig.Eap.TLS, wifiEnterpriseConfig.getEapMethod()); 719 assertEquals(CLIENT_CERTIFICATE_ALIAS, wifiEnterpriseConfig.getClientCertificateAlias()); 720 assertEquals(CA_CERTIFICATE_ALIAS, wifiEnterpriseConfig.getCaCertificateAlias()); 721 } 722 723 /** 724 * Verify that an expected WifiConfiguration will be returned for a Passpoint provider 725 * with a SIM credential. 726 * 727 * @throws Exception 728 */ 729 @Test 730 public void getWifiConfigWithSimCredential() throws Exception { 731 // Test data. 732 String fqdn = "test.com"; 733 String friendlyName = "Friendly Name"; 734 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 735 String realm = "realm.com"; 736 String imsi = "1234*"; 737 738 // Create provider. 739 PasspointConfiguration config = new PasspointConfiguration(); 740 HomeSp homeSp = new HomeSp(); 741 homeSp.setFqdn(fqdn); 742 homeSp.setFriendlyName(friendlyName); 743 homeSp.setRoamingConsortiumOis(rcOIs); 744 config.setHomeSp(homeSp); 745 Credential credential = new Credential(); 746 credential.setRealm(realm); 747 Credential.SimCredential simCredential = new Credential.SimCredential(); 748 simCredential.setImsi(imsi); 749 simCredential.setEapType(EAPConstants.EAP_SIM); 750 credential.setSimCredential(simCredential); 751 config.setCredential(credential); 752 mProvider = createProvider(config); 753 754 // Retrieve the WifiConfiguration associated with the provider, and verify the content of 755 // the configuration. Need to verify field by field since WifiConfiguration doesn't 756 // override equals() function. 757 WifiConfiguration wifiConfig = mProvider.getWifiConfig(); 758 WifiEnterpriseConfig wifiEnterpriseConfig = wifiConfig.enterpriseConfig; 759 assertEquals(fqdn, wifiConfig.FQDN); 760 assertEquals(friendlyName, wifiConfig.providerFriendlyName); 761 assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds)); 762 assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)); 763 assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)); 764 assertEquals(realm, wifiEnterpriseConfig.getRealm()); 765 assertEquals(fqdn, wifiEnterpriseConfig.getDomainSuffixMatch()); 766 assertEquals(WifiEnterpriseConfig.Eap.SIM, wifiEnterpriseConfig.getEapMethod()); 767 assertEquals(imsi, wifiEnterpriseConfig.getPlmn()); 768 } 769 770 /** 771 * Verify that an expected {@link PasspointConfiguration} will be returned when converting 772 * from a {@link WifiConfiguration} containing an user credential. 773 * 774 * @throws Exception 775 */ 776 @Test 777 public void convertFromWifiConfigWithUserCredential() throws Exception { 778 // Test data. 779 String fqdn = "test.com"; 780 String friendlyName = "Friendly Name"; 781 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 782 String realm = "realm.com"; 783 String username = "username"; 784 String password = "password"; 785 byte[] base64EncodedPw = 786 Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); 787 String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8); 788 789 // Setup WifiConfiguration for legacy Passpoint configuraiton. 790 WifiConfiguration wifiConfig = new WifiConfiguration(); 791 wifiConfig.FQDN = fqdn; 792 wifiConfig.providerFriendlyName = friendlyName; 793 wifiConfig.roamingConsortiumIds = rcOIs; 794 wifiConfig.enterpriseConfig.setIdentity(username); 795 wifiConfig.enterpriseConfig.setPassword(password); 796 wifiConfig.enterpriseConfig.setRealm(realm); 797 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); 798 wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP); 799 800 // Setup expected {@link PasspointConfiguration} 801 PasspointConfiguration passpointConfig = new PasspointConfiguration(); 802 HomeSp homeSp = new HomeSp(); 803 homeSp.setFqdn(fqdn); 804 homeSp.setFriendlyName(friendlyName); 805 homeSp.setRoamingConsortiumOis(rcOIs); 806 passpointConfig.setHomeSp(homeSp); 807 Credential credential = new Credential(); 808 Credential.UserCredential userCredential = new Credential.UserCredential(); 809 userCredential.setUsername(username); 810 userCredential.setPassword(encodedPasswordStr); 811 userCredential.setEapType(EAPConstants.EAP_TTLS); 812 userCredential.setNonEapInnerMethod("PAP"); 813 credential.setUserCredential(userCredential); 814 credential.setRealm(realm); 815 passpointConfig.setCredential(credential); 816 817 assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig)); 818 } 819 820 /** 821 * Verify that an expected {@link PasspointConfiguration} will be returned when converting 822 * from a {@link WifiConfiguration} containing a SIM credential. 823 * 824 * @throws Exception 825 */ 826 @Test 827 public void convertFromWifiConfigWithSimCredential() throws Exception { 828 // Test data. 829 String fqdn = "test.com"; 830 String friendlyName = "Friendly Name"; 831 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 832 String realm = "realm.com"; 833 String imsi = "1234"; 834 835 // Setup WifiConfiguration for legacy Passpoint configuraiton. 836 WifiConfiguration wifiConfig = new WifiConfiguration(); 837 wifiConfig.FQDN = fqdn; 838 wifiConfig.providerFriendlyName = friendlyName; 839 wifiConfig.roamingConsortiumIds = rcOIs; 840 wifiConfig.enterpriseConfig.setRealm(realm); 841 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); 842 wifiConfig.enterpriseConfig.setPlmn(imsi); 843 844 // Setup expected {@link PasspointConfiguration} 845 PasspointConfiguration passpointConfig = new PasspointConfiguration(); 846 HomeSp homeSp = new HomeSp(); 847 homeSp.setFqdn(fqdn); 848 homeSp.setFriendlyName(friendlyName); 849 homeSp.setRoamingConsortiumOis(rcOIs); 850 passpointConfig.setHomeSp(homeSp); 851 Credential credential = new Credential(); 852 Credential.SimCredential simCredential = new Credential.SimCredential(); 853 simCredential.setEapType(EAPConstants.EAP_SIM); 854 simCredential.setImsi(imsi); 855 credential.setSimCredential(simCredential); 856 credential.setRealm(realm); 857 passpointConfig.setCredential(credential); 858 859 assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig)); 860 } 861 862 /** 863 * Verify that an expected {@link PasspointConfiguration} will be returned when converting 864 * from a {@link WifiConfiguration} containing a certificate credential. 865 * 866 * @throws Exception 867 */ 868 @Test 869 public void convertFromWifiConfigWithCertCredential() throws Exception { 870 // Test data. 871 String fqdn = "test.com"; 872 String friendlyName = "Friendly Name"; 873 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 874 String realm = "realm.com"; 875 876 // Setup WifiConfiguration for legacy Passpoint configuraiton. 877 WifiConfiguration wifiConfig = new WifiConfiguration(); 878 wifiConfig.FQDN = fqdn; 879 wifiConfig.providerFriendlyName = friendlyName; 880 wifiConfig.roamingConsortiumIds = rcOIs; 881 wifiConfig.enterpriseConfig.setRealm(realm); 882 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); 883 884 // Setup expected {@link PasspointConfiguration} 885 PasspointConfiguration passpointConfig = new PasspointConfiguration(); 886 HomeSp homeSp = new HomeSp(); 887 homeSp.setFqdn(fqdn); 888 homeSp.setFriendlyName(friendlyName); 889 homeSp.setRoamingConsortiumOis(rcOIs); 890 passpointConfig.setHomeSp(homeSp); 891 Credential credential = new Credential(); 892 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 893 certCredential.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3); 894 credential.setCertCredential(certCredential); 895 credential.setRealm(realm); 896 passpointConfig.setCredential(credential); 897 898 assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig)); 899 } 900 901 /** 902 * Verify that {@link PasspointProvider#isSimCredential} will return true for provider that's 903 * backed by a SIM credential. 904 * 905 * @throws Exception 906 */ 907 @Test 908 public void providerBackedBySimCredential() throws Exception { 909 // Test data. 910 String fqdn = "test.com"; 911 String friendlyName = "Friendly Name"; 912 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 913 String realm = "realm.com"; 914 String imsi = "1234*"; 915 916 // Create provider with SIM credential. 917 PasspointConfiguration config = new PasspointConfiguration(); 918 HomeSp homeSp = new HomeSp(); 919 homeSp.setFqdn(fqdn); 920 homeSp.setFriendlyName(friendlyName); 921 homeSp.setRoamingConsortiumOis(rcOIs); 922 config.setHomeSp(homeSp); 923 Credential credential = new Credential(); 924 credential.setRealm(realm); 925 Credential.SimCredential simCredential = new Credential.SimCredential(); 926 simCredential.setImsi(imsi); 927 simCredential.setEapType(EAPConstants.EAP_SIM); 928 credential.setSimCredential(simCredential); 929 config.setCredential(credential); 930 mProvider = createProvider(config); 931 932 assertTrue(mProvider.isSimCredential()); 933 } 934 935 /** 936 * Verify that {@link PasspointProvider#isSimCredential} will return false for provider that's 937 * not backed by a SIM credential. 938 * 939 * @throws Exception 940 */ 941 @Test 942 public void providerNotBackedBySimCredential() throws Exception { 943 // Test data. 944 String fqdn = "test.com"; 945 String friendlyName = "Friendly Name"; 946 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 947 String realm = "realm.com"; 948 949 // Create provider with certificate credential. 950 PasspointConfiguration config = new PasspointConfiguration(); 951 HomeSp homeSp = new HomeSp(); 952 homeSp.setFqdn(fqdn); 953 homeSp.setFriendlyName(friendlyName); 954 homeSp.setRoamingConsortiumOis(rcOIs); 955 config.setHomeSp(homeSp); 956 Credential credential = new Credential(); 957 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 958 certCredential.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3); 959 credential.setCertCredential(certCredential); 960 credential.setRealm(realm); 961 config.setCredential(credential); 962 mProvider = createProvider(config); 963 964 assertFalse(mProvider.isSimCredential()); 965 } 966 967 /** 968 * Verify that hasEverConnected flag is set correctly using 969 * {@link PasspointProvider#setHasEverConnected}. 970 * 971 * @throws Exception 972 */ 973 @Test 974 public void setHasEverConnected() throws Exception { 975 PasspointConfiguration config = new PasspointConfiguration(); 976 HomeSp homeSp = new HomeSp(); 977 homeSp.setFqdn("test1"); 978 config.setHomeSp(homeSp); 979 Credential credential = new Credential(); 980 credential.setUserCredential(new Credential.UserCredential()); 981 config.setCredential(credential); 982 mProvider = createProvider(config); 983 verifyInstalledConfig(config, true); 984 985 assertFalse(mProvider.getHasEverConnected()); 986 mProvider.setHasEverConnected(true); 987 assertTrue(mProvider.getHasEverConnected()); 988 } 989 } 990