Home | History | Annotate | Download | only in hotspot2
      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