PasspointProviderTest.java revision 2e60a41775fc66f245e7413db72002aebe69e823
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
17package com.android.server.wifi.hotspot2;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertTrue;
22import static org.mockito.Mockito.verify;
23import static org.mockito.Mockito.when;
24import static org.mockito.MockitoAnnotations.initMocks;
25
26import android.net.wifi.EAPConstants;
27import android.net.wifi.WifiConfiguration;
28import android.net.wifi.WifiEnterpriseConfig;
29import android.net.wifi.hotspot2.PasspointConfiguration;
30import android.net.wifi.hotspot2.pps.Credential;
31import android.net.wifi.hotspot2.pps.HomeSp;
32import android.test.suitebuilder.annotation.SmallTest;
33import android.util.Base64;
34
35import com.android.server.wifi.FakeKeys;
36import com.android.server.wifi.IMSIParameter;
37import com.android.server.wifi.SIMAccessor;
38import com.android.server.wifi.WifiKeyStore;
39import com.android.server.wifi.hotspot2.anqp.ANQPElement;
40import com.android.server.wifi.hotspot2.anqp.CellularNetwork;
41import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType;
42import com.android.server.wifi.hotspot2.anqp.DomainNameElement;
43import com.android.server.wifi.hotspot2.anqp.NAIRealmData;
44import com.android.server.wifi.hotspot2.anqp.NAIRealmElement;
45import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement;
46import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement;
47import com.android.server.wifi.hotspot2.anqp.eap.AuthParam;
48import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod;
49import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth;
50
51import org.junit.Before;
52import org.junit.Test;
53import org.mockito.Mock;
54
55import java.nio.charset.StandardCharsets;
56import java.security.MessageDigest;
57import java.security.cert.X509Certificate;
58import java.util.Arrays;
59import java.util.HashMap;
60import java.util.HashSet;
61import java.util.Map;
62import java.util.Set;
63
64/**
65 * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointProvider}.
66 */
67@SmallTest
68public 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("anonymous@" + realm, wifiEnterpriseConfig.getAnonymousIdentity());
655        assertEquals(WifiEnterpriseConfig.Eap.TTLS, wifiEnterpriseConfig.getEapMethod());
656        assertEquals(WifiEnterpriseConfig.Phase2.MSCHAPV2, wifiEnterpriseConfig.getPhase2Method());
657        assertEquals(username, wifiEnterpriseConfig.getIdentity());
658        assertEquals(password, wifiEnterpriseConfig.getPassword());
659        assertEquals(CA_CERTIFICATE_ALIAS, wifiEnterpriseConfig.getCaCertificateAlias());
660    }
661
662    /**
663     * Verify that an expected WifiConfiguration will be returned for a Passpoint provider
664     * with a certificate credential.
665     *
666     * @throws Exception
667     */
668    @Test
669    public void getWifiConfigWithCertCredential() throws Exception {
670        // Test data.
671        String fqdn = "test.com";
672        String friendlyName = "Friendly Name";
673        long[] rcOIs = new long[] {0x1234L, 0x2345L};
674        String realm = "realm.com";
675
676        // Create provider.
677        PasspointConfiguration config = new PasspointConfiguration();
678        HomeSp homeSp = new HomeSp();
679        homeSp.setFqdn(fqdn);
680        homeSp.setFriendlyName(friendlyName);
681        homeSp.setRoamingConsortiumOis(rcOIs);
682        config.setHomeSp(homeSp);
683        Credential credential = new Credential();
684        credential.setRealm(realm);
685        Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
686        certCredential.setCertSha256Fingerprint(
687                MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded()));
688        credential.setCertCredential(certCredential);
689        credential.setCaCertificate(FakeKeys.CA_CERT0);
690        credential.setClientPrivateKey(FakeKeys.RSA_KEY1);
691        credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT});
692        config.setCredential(credential);
693        mProvider = createProvider(config);
694
695        // Install certificate.
696        when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_NAME, FakeKeys.CA_CERT0))
697                .thenReturn(true);
698        when(mKeyStore.putKeyInKeyStore(CLIENT_PRIVATE_KEY_NAME, FakeKeys.RSA_KEY1))
699                .thenReturn(true);
700        when(mKeyStore.putCertInKeyStore(CLIENT_CERTIFICATE_NAME, FakeKeys.CLIENT_CERT))
701                .thenReturn(true);
702        assertTrue(mProvider.installCertsAndKeys());
703
704        // Retrieve the WifiConfiguration associated with the provider, and verify the content of
705        // the configuration.  Need to verify field by field since WifiConfiguration doesn't
706        // override equals() function.
707        WifiConfiguration wifiConfig = mProvider.getWifiConfig();
708        WifiEnterpriseConfig wifiEnterpriseConfig = wifiConfig.enterpriseConfig;
709        assertEquals(fqdn, wifiConfig.FQDN);
710        assertEquals(friendlyName, wifiConfig.providerFriendlyName);
711        assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds));
712        assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
713        assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
714        assertEquals(realm, wifiEnterpriseConfig.getRealm());
715        assertEquals("anonymous@" + realm, wifiEnterpriseConfig.getAnonymousIdentity());
716        assertEquals(WifiEnterpriseConfig.Eap.TLS, wifiEnterpriseConfig.getEapMethod());
717        assertEquals(CLIENT_CERTIFICATE_ALIAS, wifiEnterpriseConfig.getClientCertificateAlias());
718        assertEquals(CA_CERTIFICATE_ALIAS, wifiEnterpriseConfig.getCaCertificateAlias());
719    }
720
721    /**
722     * Verify that an expected WifiConfiguration will be returned for a Passpoint provider
723     * with a SIM credential.
724     *
725     * @throws Exception
726     */
727    @Test
728    public void getWifiConfigWithSimCredential() throws Exception {
729        // Test data.
730        String fqdn = "test.com";
731        String friendlyName = "Friendly Name";
732        long[] rcOIs = new long[] {0x1234L, 0x2345L};
733        String realm = "realm.com";
734        String imsi = "1234*";
735
736        // Create provider.
737        PasspointConfiguration config = new PasspointConfiguration();
738        HomeSp homeSp = new HomeSp();
739        homeSp.setFqdn(fqdn);
740        homeSp.setFriendlyName(friendlyName);
741        homeSp.setRoamingConsortiumOis(rcOIs);
742        config.setHomeSp(homeSp);
743        Credential credential = new Credential();
744        credential.setRealm(realm);
745        Credential.SimCredential simCredential = new Credential.SimCredential();
746        simCredential.setImsi(imsi);
747        simCredential.setEapType(EAPConstants.EAP_SIM);
748        credential.setSimCredential(simCredential);
749        config.setCredential(credential);
750        mProvider = createProvider(config);
751
752        // Retrieve the WifiConfiguration associated with the provider, and verify the content of
753        // the configuration.  Need to verify field by field since WifiConfiguration doesn't
754        // override equals() function.
755        WifiConfiguration wifiConfig = mProvider.getWifiConfig();
756        WifiEnterpriseConfig wifiEnterpriseConfig = wifiConfig.enterpriseConfig;
757        assertEquals(fqdn, wifiConfig.FQDN);
758        assertEquals(friendlyName, wifiConfig.providerFriendlyName);
759        assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds));
760        assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
761        assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
762        assertEquals(realm, wifiEnterpriseConfig.getRealm());
763        assertEquals(WifiEnterpriseConfig.Eap.SIM, wifiEnterpriseConfig.getEapMethod());
764        assertEquals(imsi, wifiEnterpriseConfig.getPlmn());
765    }
766
767    /**
768     * Verify that an expected {@link PasspointConfiguration} will be returned when converting
769     * from a {@link WifiConfiguration} containing an user credential.
770     *
771     * @throws Exception
772     */
773    @Test
774    public void convertFromWifiConfigWithUserCredential() throws Exception {
775        // Test data.
776        String fqdn = "test.com";
777        String friendlyName = "Friendly Name";
778        long[] rcOIs = new long[] {0x1234L, 0x2345L};
779        String realm = "realm.com";
780        String username = "username";
781        String password = "password";
782        byte[] base64EncodedPw =
783                Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT);
784        String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8);
785
786        // Setup WifiConfiguration for legacy Passpoint configuraiton.
787        WifiConfiguration wifiConfig = new WifiConfiguration();
788        wifiConfig.FQDN = fqdn;
789        wifiConfig.providerFriendlyName = friendlyName;
790        wifiConfig.roamingConsortiumIds = rcOIs;
791        wifiConfig.enterpriseConfig.setIdentity(username);
792        wifiConfig.enterpriseConfig.setPassword(password);
793        wifiConfig.enterpriseConfig.setRealm(realm);
794        wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
795        wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP);
796
797        // Setup expected {@link PasspointConfiguration}
798        PasspointConfiguration passpointConfig = new PasspointConfiguration();
799        HomeSp homeSp = new HomeSp();
800        homeSp.setFqdn(fqdn);
801        homeSp.setFriendlyName(friendlyName);
802        homeSp.setRoamingConsortiumOis(rcOIs);
803        passpointConfig.setHomeSp(homeSp);
804        Credential credential = new Credential();
805        Credential.UserCredential userCredential = new Credential.UserCredential();
806        userCredential.setUsername(username);
807        userCredential.setPassword(encodedPasswordStr);
808        userCredential.setEapType(EAPConstants.EAP_TTLS);
809        userCredential.setNonEapInnerMethod("PAP");
810        credential.setUserCredential(userCredential);
811        credential.setRealm(realm);
812        passpointConfig.setCredential(credential);
813
814        assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig));
815    }
816
817    /**
818     * Verify that an expected {@link PasspointConfiguration} will be returned when converting
819     * from a {@link WifiConfiguration} containing a SIM credential.
820     *
821     * @throws Exception
822     */
823    @Test
824    public void convertFromWifiConfigWithSimCredential() throws Exception {
825        // Test data.
826        String fqdn = "test.com";
827        String friendlyName = "Friendly Name";
828        long[] rcOIs = new long[] {0x1234L, 0x2345L};
829        String realm = "realm.com";
830        String imsi = "1234";
831
832        // Setup WifiConfiguration for legacy Passpoint configuraiton.
833        WifiConfiguration wifiConfig = new WifiConfiguration();
834        wifiConfig.FQDN = fqdn;
835        wifiConfig.providerFriendlyName = friendlyName;
836        wifiConfig.roamingConsortiumIds = rcOIs;
837        wifiConfig.enterpriseConfig.setRealm(realm);
838        wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
839        wifiConfig.enterpriseConfig.setPlmn(imsi);
840
841        // Setup expected {@link PasspointConfiguration}
842        PasspointConfiguration passpointConfig = new PasspointConfiguration();
843        HomeSp homeSp = new HomeSp();
844        homeSp.setFqdn(fqdn);
845        homeSp.setFriendlyName(friendlyName);
846        homeSp.setRoamingConsortiumOis(rcOIs);
847        passpointConfig.setHomeSp(homeSp);
848        Credential credential = new Credential();
849        Credential.SimCredential simCredential = new Credential.SimCredential();
850        simCredential.setEapType(EAPConstants.EAP_SIM);
851        simCredential.setImsi(imsi);
852        credential.setSimCredential(simCredential);
853        credential.setRealm(realm);
854        passpointConfig.setCredential(credential);
855
856        assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig));
857    }
858
859    /**
860     * Verify that an expected {@link PasspointConfiguration} will be returned when converting
861     * from a {@link WifiConfiguration} containing a certificate credential.
862     *
863     * @throws Exception
864     */
865    @Test
866    public void convertFromWifiConfigWithCertCredential() throws Exception {
867        // Test data.
868        String fqdn = "test.com";
869        String friendlyName = "Friendly Name";
870        long[] rcOIs = new long[] {0x1234L, 0x2345L};
871        String realm = "realm.com";
872
873        // Setup WifiConfiguration for legacy Passpoint configuraiton.
874        WifiConfiguration wifiConfig = new WifiConfiguration();
875        wifiConfig.FQDN = fqdn;
876        wifiConfig.providerFriendlyName = friendlyName;
877        wifiConfig.roamingConsortiumIds = rcOIs;
878        wifiConfig.enterpriseConfig.setRealm(realm);
879        wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
880
881        // Setup expected {@link PasspointConfiguration}
882        PasspointConfiguration passpointConfig = new PasspointConfiguration();
883        HomeSp homeSp = new HomeSp();
884        homeSp.setFqdn(fqdn);
885        homeSp.setFriendlyName(friendlyName);
886        homeSp.setRoamingConsortiumOis(rcOIs);
887        passpointConfig.setHomeSp(homeSp);
888        Credential credential = new Credential();
889        Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
890        certCredential.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3);
891        credential.setCertCredential(certCredential);
892        credential.setRealm(realm);
893        passpointConfig.setCredential(credential);
894
895        assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig));
896    }
897
898}
899