PasspointProviderTest.java revision 4f4d745ca28b915ea4a7c91ec5df3ea8a2db64ad
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 String CA_CERTIFICATE_ALIAS = "CACERT_HS2_12";
71    private static final String CLIENT_CERTIFICATE_ALIAS = "USRCERT_HS2_12";
72    private static final String CLIENT_PRIVATE_KEY_ALIAS = "USRPKEY_HS2_12";
73    private static final String ALIAS_SUFFIX = "HS2_12";
74
75    @Mock WifiKeyStore mKeyStore;
76    @Mock SIMAccessor mSimAccessor;
77    PasspointProvider mProvider;
78
79    /** Sets up test. */
80    @Before
81    public void setUp() throws Exception {
82        initMocks(this);
83    }
84
85    /**
86     * Helper function for creating a provider instance for testing.
87     *
88     * @param config The configuration associated with the provider
89     * @return {@link com.android.server.wifi.hotspot2.PasspointProvider}
90     */
91    private PasspointProvider createProvider(PasspointConfiguration config) {
92        return new PasspointProvider(config, mKeyStore, mSimAccessor, PROVIDER_ID);
93    }
94
95    /**
96     * Verify that the configuration associated with the provider is the same or not the same
97     * as the expected configuration.
98     *
99     * @param expectedConfig The expected configuration
100     * @param equals Flag indicating equality or inequality check
101     */
102    private void verifyInstalledConfig(PasspointConfiguration expectedConfig, boolean equals) {
103        PasspointConfiguration actualConfig = mProvider.getConfig();
104        if (equals) {
105            assertTrue(actualConfig.equals(expectedConfig));
106        } else {
107            assertFalse(actualConfig.equals(expectedConfig));
108        }
109    }
110
111    /**
112     * Helper function for creating a Domain Name ANQP element.
113     *
114     * @param domains List of domain names
115     * @return {@link DomainNameElement}
116     */
117    private DomainNameElement createDomainNameElement(String[] domains) {
118        return new DomainNameElement(Arrays.asList(domains));
119    }
120
121    /**
122     * Helper function for creating a NAI Realm ANQP element.
123     *
124     * @param realm The realm of the network
125     * @param eapMethodID EAP Method ID
126     * @param authParam Authentication parameter
127     * @return {@link NAIRealmElement}
128     */
129    private NAIRealmElement createNAIRealmElement(String realm, int eapMethodID,
130            AuthParam authParam) {
131        Map<Integer, Set<AuthParam>> authParamMap = new HashMap<>();
132        if (authParam != null) {
133            Set<AuthParam> authSet = new HashSet<>();
134            authSet.add(authParam);
135            authParamMap.put(authParam.getAuthTypeID(), authSet);
136        }
137        EAPMethod eapMethod = new EAPMethod(eapMethodID, authParamMap);
138        NAIRealmData realmData = new NAIRealmData(Arrays.asList(new String[] {realm}),
139                Arrays.asList(new EAPMethod[] {eapMethod}));
140        return new NAIRealmElement(Arrays.asList(new NAIRealmData[] {realmData}));
141    }
142
143    /**
144     * Helper function for creating a Roaming Consortium ANQP element.
145     *
146     * @param rcOIs Roaming consortium OIs
147     * @return {@link RoamingConsortiumElement}
148     */
149    private RoamingConsortiumElement createRoamingConsortiumElement(Long[] rcOIs) {
150        return new RoamingConsortiumElement(Arrays.asList(rcOIs));
151    }
152
153    /**
154     * Helper function for creating a 3GPP Network ANQP element.
155     *
156     * @param imsiList List of IMSI to be included in a 3GPP Network
157     * @return {@link ThreeGPPNetworkElement}
158     */
159    private ThreeGPPNetworkElement createThreeGPPNetworkElement(String[] imsiList) {
160        CellularNetwork network = new CellularNetwork(Arrays.asList(imsiList));
161        return new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[] {network}));
162    }
163
164    /**
165     * Verify that modification to the configuration used for creating PasspointProvider
166     * will not change the configuration stored inside the PasspointProvider.
167     *
168     * @throws Exception
169     */
170    @Test
171    public void verifyModifyOriginalConfig() throws Exception {
172        // Create a dummy PasspointConfiguration.
173        PasspointConfiguration config = new PasspointConfiguration();
174        HomeSP homeSp = new HomeSP();
175        homeSp.setFqdn("test1");
176        config.setHomeSp(homeSp);
177        Credential credential = new Credential();
178        credential.setUserCredential(new Credential.UserCredential());
179        config.setCredential(credential);
180        mProvider = createProvider(config);
181        verifyInstalledConfig(config, true);
182
183        // Modify the original configuration, the configuration maintained by the provider
184        // should be unchanged.
185        config.getHomeSp().setFqdn("test2");
186        verifyInstalledConfig(config, false);
187    }
188
189    /**
190     * Verify that modification to the configuration retrieved from the PasspointProvider
191     * will not change the configuration stored inside the PasspointProvider.
192     *
193     * @throws Exception
194     */
195    @Test
196    public void verifyModifyRetrievedConfig() throws Exception {
197        // Create a dummy PasspointConfiguration.
198        PasspointConfiguration config = new PasspointConfiguration();
199        HomeSP homeSp = new HomeSP();
200        homeSp.setFqdn("test1");
201        config.setHomeSp(homeSp);
202        Credential credential = new Credential();
203        credential.setUserCredential(new Credential.UserCredential());
204        config.setCredential(credential);
205        mProvider = createProvider(config);
206        verifyInstalledConfig(config, true);
207
208        // Modify the retrieved configuration, verify the configuration maintained by the
209        // provider should be unchanged.
210        PasspointConfiguration retrievedConfig = mProvider.getConfig();
211        retrievedConfig.getHomeSp().setFqdn("test2");
212        verifyInstalledConfig(retrievedConfig, false);
213    }
214
215    /**
216     * Verify a successful installation of certificates and key.
217     *
218     * @throws Exception
219     */
220    @Test
221    public void installCertsAndKeysSuccess() throws Exception {
222        // Create a dummy configuration with certificate credential.
223        PasspointConfiguration config = new PasspointConfiguration();
224        Credential credential = new Credential();
225        Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
226        certCredential.setCertSha256Fingerprint(
227                MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded()));
228        credential.setCertCredential(certCredential);
229        credential.setCaCertificate(FakeKeys.CA_CERT0);
230        credential.setClientPrivateKey(FakeKeys.RSA_KEY1);
231        credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT});
232        config.setCredential(credential);
233        mProvider = createProvider(config);
234
235        // Install client certificate and key to the keystore successfully.
236        when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
237                .thenReturn(true);
238        when(mKeyStore.putKeyInKeyStore(CLIENT_PRIVATE_KEY_ALIAS, FakeKeys.RSA_KEY1))
239                .thenReturn(true);
240        when(mKeyStore.putCertInKeyStore(CLIENT_CERTIFICATE_ALIAS, FakeKeys.CLIENT_CERT))
241                .thenReturn(true);
242        assertTrue(mProvider.installCertsAndKeys());
243
244        // Verify client certificate and key in the configuration gets cleared and aliases
245        // are set correctly.
246        PasspointConfiguration curConfig = mProvider.getConfig();
247        assertTrue(curConfig.getCredential().getCaCertificate() == null);
248        assertTrue(curConfig.getCredential().getClientPrivateKey() == null);
249        assertTrue(curConfig.getCredential().getClientCertificateChain() == null);
250        assertTrue(mProvider.getCaCertificateAlias().equals(CA_CERTIFICATE_ALIAS));
251        assertTrue(mProvider.getClientPrivateKeyAlias().equals(CLIENT_PRIVATE_KEY_ALIAS));
252        assertTrue(mProvider.getClientCertificateAlias().equals(CLIENT_CERTIFICATE_ALIAS));
253    }
254
255    /**
256     * Verify a failure installation of certificates and key.
257     *
258     * @throws Exception
259     */
260    @Test
261    public void installCertsAndKeysFailure() throws Exception {
262        // Create a dummy configuration with certificate credential.
263        PasspointConfiguration config = new PasspointConfiguration();
264        Credential credential = new Credential();
265        Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
266        certCredential.setCertSha256Fingerprint(
267                MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded()));
268        credential.setCertCredential(certCredential);
269        credential.setCaCertificate(FakeKeys.CA_CERT0);
270        credential.setClientPrivateKey(FakeKeys.RSA_KEY1);
271        credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT});
272        config.setCredential(credential);
273        mProvider = createProvider(config);
274
275        // Failed to install client certificate to the keystore.
276        when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
277                .thenReturn(true);
278        when(mKeyStore.putKeyInKeyStore(CLIENT_PRIVATE_KEY_ALIAS, FakeKeys.RSA_KEY1))
279                .thenReturn(true);
280        when(mKeyStore.putCertInKeyStore(CLIENT_CERTIFICATE_ALIAS, FakeKeys.CLIENT_CERT))
281                .thenReturn(false);
282        assertFalse(mProvider.installCertsAndKeys());
283
284        // Verify certificates and key in the configuration are not cleared and aliases
285        // are not set.
286        PasspointConfiguration curConfig = mProvider.getConfig();
287        assertTrue(curConfig.getCredential().getCaCertificate() != null);
288        assertTrue(curConfig.getCredential().getClientCertificateChain() != null);
289        assertTrue(curConfig.getCredential().getClientPrivateKey() != null);
290        assertTrue(mProvider.getCaCertificateAlias() == null);
291        assertTrue(mProvider.getClientPrivateKeyAlias() == null);
292        assertTrue(mProvider.getClientCertificateAlias() == null);
293    }
294
295    /**
296     * Verify a successful uninstallation of certificates and key.
297     */
298    @Test
299    public void uninstallCertsAndKeys() throws Exception {
300        // Create a dummy configuration with certificate credential.
301        PasspointConfiguration config = new PasspointConfiguration();
302        Credential credential = new Credential();
303        Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
304        certCredential.setCertSha256Fingerprint(
305                MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded()));
306        credential.setCertCredential(certCredential);
307        credential.setCaCertificate(FakeKeys.CA_CERT0);
308        credential.setClientPrivateKey(FakeKeys.RSA_KEY1);
309        credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT});
310        config.setCredential(credential);
311        mProvider = createProvider(config);
312
313        // Install client certificate and key to the keystore successfully.
314        when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
315                .thenReturn(true);
316        when(mKeyStore.putKeyInKeyStore(CLIENT_PRIVATE_KEY_ALIAS, FakeKeys.RSA_KEY1))
317                .thenReturn(true);
318        when(mKeyStore.putCertInKeyStore(CLIENT_CERTIFICATE_ALIAS, FakeKeys.CLIENT_CERT))
319                .thenReturn(true);
320        assertTrue(mProvider.installCertsAndKeys());
321        assertTrue(mProvider.getCaCertificateAlias().equals(CA_CERTIFICATE_ALIAS));
322        assertTrue(mProvider.getClientPrivateKeyAlias().equals(CLIENT_PRIVATE_KEY_ALIAS));
323        assertTrue(mProvider.getClientCertificateAlias().equals(CLIENT_CERTIFICATE_ALIAS));
324
325        // Uninstall certificates and key from the keystore.
326        mProvider.uninstallCertsAndKeys();
327        verify(mKeyStore).removeEntryFromKeyStore(CA_CERTIFICATE_ALIAS);
328        verify(mKeyStore).removeEntryFromKeyStore(CLIENT_CERTIFICATE_ALIAS);
329        verify(mKeyStore).removeEntryFromKeyStore(CLIENT_PRIVATE_KEY_ALIAS);
330        assertTrue(mProvider.getCaCertificateAlias() == null);
331        assertTrue(mProvider.getClientPrivateKeyAlias() == null);
332        assertTrue(mProvider.getClientCertificateAlias() == null);
333    }
334
335    /**
336     * Verify that a provider is a home provider when its FQDN matches a domain name in the
337     * Domain Name ANQP element and no NAI realm is provided.
338     *
339     * @throws Exception
340     */
341    @Test
342    public void matchFQDNWithoutNAIRealm() throws Exception {
343        String testDomain = "test.com";
344
345        // Setup test provider.
346        PasspointConfiguration config = new PasspointConfiguration();
347        HomeSP homeSp = new HomeSP();
348        homeSp.setFqdn(testDomain);
349        config.setHomeSp(homeSp);
350        Credential credential = new Credential();
351        Credential.UserCredential userCredential = new Credential.UserCredential();
352        userCredential.setNonEapInnerMethod("MS-CHAP-V2");
353        credential.setUserCredential(userCredential);
354        config.setCredential(credential);
355        mProvider = createProvider(config);
356
357        // Setup ANQP elements.
358        Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
359        anqpElementMap.put(ANQPElementType.ANQPDomName,
360                createDomainNameElement(new String[] {testDomain}));
361
362        assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap));
363    }
364
365    /**
366     * Verify that a provider is a home provider when its FQDN matches a domain name in the
367     * Domain Name ANQP element and the provider's credential matches the NAI realm provided.
368     *
369     * @throws Exception
370     */
371    @Test
372    public void matchFQDNWithNAIRealmMatch() throws Exception {
373        String testDomain = "test.com";
374        String testRealm = "realm.com";
375
376        // Setup test provider.
377        PasspointConfiguration config = new PasspointConfiguration();
378        HomeSP homeSp = new HomeSP();
379        homeSp.setFqdn(testDomain);
380        config.setHomeSp(homeSp);
381        Credential credential = new Credential();
382        credential.setRealm(testRealm);
383        Credential.UserCredential userCredential = new Credential.UserCredential();
384        userCredential.setNonEapInnerMethod("MS-CHAP-V2");
385        credential.setUserCredential(userCredential);
386        config.setCredential(credential);
387        mProvider = createProvider(config);
388
389        // Setup Domain Name ANQP element.
390        Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
391        anqpElementMap.put(ANQPElementType.ANQPDomName,
392                createDomainNameElement(new String[] {testDomain}));
393        anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
394                createNAIRealmElement(testRealm, EAPConstants.EAP_TTLS,
395                        new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
396
397        assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap));
398    }
399
400    /**
401     * Verify that there is no match when the provider's FQDN matches a domain name in the
402     * Domain Name ANQP element but the provider's credential doesn't match the authentication
403     * method provided in the NAI realm.
404     *
405     * @throws Exception
406     */
407    @Test
408    public void matchFQDNWithNAIRealmMismatch() throws Exception {
409        String testDomain = "test.com";
410        String testRealm = "realm.com";
411
412        // Setup test provider.
413        PasspointConfiguration config = new PasspointConfiguration();
414        HomeSP homeSp = new HomeSP();
415        homeSp.setFqdn(testDomain);
416        config.setHomeSp(homeSp);
417        Credential credential = new Credential();
418        credential.setRealm(testRealm);
419        Credential.UserCredential userCredential = new Credential.UserCredential();
420        userCredential.setNonEapInnerMethod("MS-CHAP-V2");
421        credential.setUserCredential(userCredential);
422        config.setCredential(credential);
423        mProvider = createProvider(config);
424
425        // Setup Domain Name ANQP element.
426        Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
427        anqpElementMap.put(ANQPElementType.ANQPDomName,
428                createDomainNameElement(new String[] {testDomain}));
429        anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
430                createNAIRealmElement(testRealm, EAPConstants.EAP_TLS, null));
431
432        assertEquals(PasspointMatch.None, mProvider.match(anqpElementMap));
433    }
434
435    /**
436     * Verify that a provider is a home provider when its SIM credential matches an 3GPP network
437     * domain name in the Domain Name ANQP element.
438     *
439     * @throws Exception
440     */
441    @Test
442    public void match3GPPNetworkDomainName() throws Exception {
443        String testImsi = "1234567890";
444
445        // Setup test provider.
446        PasspointConfiguration config = new PasspointConfiguration();
447        config.setHomeSp(new HomeSP());
448        Credential credential = new Credential();
449        Credential.SimCredential simCredential = new Credential.SimCredential();
450        simCredential.setImsi(testImsi);
451        credential.setSimCredential(simCredential);
452        config.setCredential(credential);
453        when(mSimAccessor.getMatchingImsis(new IMSIParameter(testImsi, false)))
454                .thenReturn(Arrays.asList(new String[] {testImsi}));
455        mProvider = createProvider(config);
456
457        // Setup Domain Name ANQP element.
458        Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
459        anqpElementMap.put(ANQPElementType.ANQPDomName,
460                createDomainNameElement(new String[] {"wlan.mnc456.mcc123.3gppnetwork.org"}));
461
462        assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap));
463    }
464
465    /**
466     * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI
467     * in the roaming consortium ANQP element.
468     *
469     * @throws Exception
470     */
471    @Test
472    public void matchRoamingConsortium() throws Exception {
473        long[] providerRCOIs = new long[] {0x1234L, 0x2345L};
474        Long[] anqpRCOIs = new Long[] {0x1234L, 0x2133L};
475
476        // Setup test provider.
477        PasspointConfiguration config = new PasspointConfiguration();
478        HomeSP homeSp = new HomeSP();
479        homeSp.setRoamingConsortiumOIs(providerRCOIs);
480        config.setHomeSp(homeSp);
481        Credential credential = new Credential();
482        Credential.UserCredential userCredential = new Credential.UserCredential();
483        userCredential.setNonEapInnerMethod("MS-CHAP-V2");
484        credential.setUserCredential(userCredential);
485        config.setCredential(credential);
486        mProvider = createProvider(config);
487
488        // Setup Roaming Consortium ANQP element.
489        Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
490        anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
491                createRoamingConsortiumElement(anqpRCOIs));
492
493        assertEquals(PasspointMatch.RoamingProvider, mProvider.match(anqpElementMap));
494    }
495
496    /**
497     * Verify that a provider is a roaming provider when the provider's IMSI parameter and an
498     * IMSI from the SIM card matches a MCC-MNC in the 3GPP Network ANQP element.
499     *
500     * @throws Exception
501     */
502    @Test
503    public void matchThreeGPPNetwork() throws Exception {
504        String testImsi = "1234567890";
505
506        // Setup test provider.
507        PasspointConfiguration config = new PasspointConfiguration();
508        config.setHomeSp(new HomeSP());
509        Credential credential = new Credential();
510        Credential.SimCredential simCredential = new Credential.SimCredential();
511        simCredential.setImsi(testImsi);
512        credential.setSimCredential(simCredential);
513        config.setCredential(credential);
514        when(mSimAccessor.getMatchingImsis(new IMSIParameter(testImsi, false)))
515                .thenReturn(Arrays.asList(new String[] {testImsi}));
516        mProvider = createProvider(config);
517
518        // Setup 3GPP Network ANQP element.
519        Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
520        anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork,
521                createThreeGPPNetworkElement(new String[] {"123456"}));
522
523        assertEquals(PasspointMatch.RoamingProvider, mProvider.match(anqpElementMap));
524    }
525
526    /**
527     * Verify that a provider is a roaming provider when its credential matches a NAI realm in
528     * the NAI Realm ANQP element.
529     *
530     * @throws Exception
531     */
532    @Test
533    public void matchNAIRealm() throws Exception {
534        String testRealm = "realm.com";
535
536        // Setup test provider.
537        PasspointConfiguration config = new PasspointConfiguration();
538        config.setHomeSp(new HomeSP());
539        Credential credential = new Credential();
540        credential.setRealm(testRealm);
541        Credential.UserCredential userCredential = new Credential.UserCredential();
542        userCredential.setNonEapInnerMethod("MS-CHAP-V2");
543        credential.setUserCredential(userCredential);
544        config.setCredential(credential);
545        mProvider = createProvider(config);
546
547        // Setup NAI Realm ANQP element.
548        Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
549        anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
550                createNAIRealmElement(testRealm, EAPConstants.EAP_TTLS,
551                        new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
552
553        assertEquals(PasspointMatch.RoamingProvider, mProvider.match(anqpElementMap));
554    }
555
556    /**
557     * Verify that a provider is a home provider when its FQDN, roaming consortium OI, and
558     * IMSI all matched against the ANQP elements, since we prefer matching home provider over
559     * roaming provider.
560     *
561     * @throws Exception
562     */
563    @Test
564    public void matchHomeOverRoamingProvider() throws Exception {
565        // Setup test data.
566        String testDomain = "test.com";
567        String testImsi = "1234567890";
568        long[] providerRCOIs = new long[] {0x1234L, 0x2345L};
569        Long[] anqpRCOIs = new Long[] {0x1234L, 0x2133L};
570
571        // Setup test provider.
572        PasspointConfiguration config = new PasspointConfiguration();
573        HomeSP homeSp = new HomeSP();
574        homeSp.setFqdn(testDomain);
575        homeSp.setRoamingConsortiumOIs(providerRCOIs);
576        config.setHomeSp(homeSp);
577        Credential credential = new Credential();
578        Credential.SimCredential simCredential = new Credential.SimCredential();
579        simCredential.setImsi(testImsi);
580        credential.setSimCredential(simCredential);
581        config.setCredential(credential);
582        when(mSimAccessor.getMatchingImsis(new IMSIParameter(testImsi, false)))
583                .thenReturn(Arrays.asList(new String[] {testImsi}));
584        mProvider = createProvider(config);
585
586        // Setup ANQP elements.
587        Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
588        anqpElementMap.put(ANQPElementType.ANQPDomName,
589                createDomainNameElement(new String[] {testDomain}));
590        anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
591                createRoamingConsortiumElement(anqpRCOIs));
592        anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork,
593                createThreeGPPNetworkElement(new String[] {"123456"}));
594
595        assertEquals(PasspointMatch.HomeProvider, mProvider.match(anqpElementMap));
596    }
597
598    /**
599     * Verify that an expected WifiConfiguration will be returned for a Passpoint provider
600     * with an user credential.
601     *
602     * @throws Exception
603     */
604    @Test
605    public void getWifiConfigWithUserCredential() throws Exception {
606        // Test data.
607        String fqdn = "test.com";
608        String friendlyName = "Friendly Name";
609        long[] rcOIs = new long[] {0x1234L, 0x2345L};
610        String realm = "realm.com";
611        String username = "username";
612        String password = "password";
613        byte[] base64EncodedPw =
614                Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT);
615        String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8);
616
617        // Create provider.
618        PasspointConfiguration config = new PasspointConfiguration();
619        HomeSP homeSp = new HomeSP();
620        homeSp.setFqdn(fqdn);
621        homeSp.setFriendlyName(friendlyName);
622        homeSp.setRoamingConsortiumOIs(rcOIs);
623        config.setHomeSp(homeSp);
624        Credential credential = new Credential();
625        credential.setRealm(realm);
626        Credential.UserCredential userCredential = new Credential.UserCredential();
627        userCredential.setUsername(username);
628        userCredential.setPassword(encodedPasswordStr);
629        userCredential.setNonEapInnerMethod("MS-CHAP-V2");
630        credential.setUserCredential(userCredential);
631        credential.setCaCertificate(FakeKeys.CA_CERT0);
632        config.setCredential(credential);
633        mProvider = createProvider(config);
634
635        // Install certificate.
636        when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
637                .thenReturn(true);
638        assertTrue(mProvider.installCertsAndKeys());
639
640        // Retrieve the WifiConfiguration associated with the provider, and verify the content of
641        // the configuration.  Need to verify field by field since WifiConfiguration doesn't
642        // override equals() function.
643        WifiConfiguration wifiConfig = mProvider.getWifiConfig();
644        WifiEnterpriseConfig wifiEnterpriseConfig = wifiConfig.enterpriseConfig;
645        assertEquals(fqdn, wifiConfig.FQDN);
646        assertEquals(friendlyName, wifiConfig.providerFriendlyName);
647        assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds));
648        assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
649        assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
650        assertEquals(realm, wifiEnterpriseConfig.getRealm());
651        assertEquals("anonymous@" + realm, wifiEnterpriseConfig.getAnonymousIdentity());
652        assertEquals(WifiEnterpriseConfig.Eap.TTLS, wifiEnterpriseConfig.getEapMethod());
653        assertEquals(WifiEnterpriseConfig.Phase2.MSCHAPV2, wifiEnterpriseConfig.getPhase2Method());
654        assertEquals(username, wifiEnterpriseConfig.getIdentity());
655        assertEquals(password, wifiEnterpriseConfig.getPassword());
656        assertEquals(ALIAS_SUFFIX, wifiEnterpriseConfig.getCaCertificateAlias());
657    }
658
659    /**
660     * Verify that an expected WifiConfiguration will be returned for a Passpoint provider
661     * with a certificate credential.
662     *
663     * @throws Exception
664     */
665    @Test
666    public void getWifiConfigWithCertCredential() throws Exception {
667        // Test data.
668        String fqdn = "test.com";
669        String friendlyName = "Friendly Name";
670        long[] rcOIs = new long[] {0x1234L, 0x2345L};
671        String realm = "realm.com";
672
673        // Create provider.
674        PasspointConfiguration config = new PasspointConfiguration();
675        HomeSP homeSp = new HomeSP();
676        homeSp.setFqdn(fqdn);
677        homeSp.setFriendlyName(friendlyName);
678        homeSp.setRoamingConsortiumOIs(rcOIs);
679        config.setHomeSp(homeSp);
680        Credential credential = new Credential();
681        credential.setRealm(realm);
682        Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
683        certCredential.setCertSha256Fingerprint(
684                MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded()));
685        credential.setCertCredential(certCredential);
686        credential.setCaCertificate(FakeKeys.CA_CERT0);
687        credential.setClientPrivateKey(FakeKeys.RSA_KEY1);
688        credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT});
689        config.setCredential(credential);
690        mProvider = createProvider(config);
691
692        // Install certificate.
693        when(mKeyStore.putCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
694                .thenReturn(true);
695        when(mKeyStore.putKeyInKeyStore(CLIENT_PRIVATE_KEY_ALIAS, FakeKeys.RSA_KEY1))
696                .thenReturn(true);
697        when(mKeyStore.putCertInKeyStore(CLIENT_CERTIFICATE_ALIAS, FakeKeys.CLIENT_CERT))
698                .thenReturn(true);
699        assertTrue(mProvider.installCertsAndKeys());
700
701        // Retrieve the WifiConfiguration associated with the provider, and verify the content of
702        // the configuration.  Need to verify field by field since WifiConfiguration doesn't
703        // override equals() function.
704        WifiConfiguration wifiConfig = mProvider.getWifiConfig();
705        WifiEnterpriseConfig wifiEnterpriseConfig = wifiConfig.enterpriseConfig;
706        assertEquals(fqdn, wifiConfig.FQDN);
707        assertEquals(friendlyName, wifiConfig.providerFriendlyName);
708        assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds));
709        assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
710        assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
711        assertEquals(realm, wifiEnterpriseConfig.getRealm());
712        assertEquals("anonymous@" + realm, wifiEnterpriseConfig.getAnonymousIdentity());
713        assertEquals(WifiEnterpriseConfig.Eap.TLS, wifiEnterpriseConfig.getEapMethod());
714        assertEquals(ALIAS_SUFFIX, wifiEnterpriseConfig.getClientCertificateAlias());
715        assertEquals(ALIAS_SUFFIX, wifiEnterpriseConfig.getCaCertificateAlias());
716    }
717
718    /**
719     * Verify that an expected WifiConfiguration will be returned for a Passpoint provider
720     * with a SIM credential.
721     *
722     * @throws Exception
723     */
724    @Test
725    public void getWifiConfigWithSimCredential() throws Exception {
726        // Test data.
727        String fqdn = "test.com";
728        String friendlyName = "Friendly Name";
729        long[] rcOIs = new long[] {0x1234L, 0x2345L};
730        String realm = "realm.com";
731        String imsi = "1234*";
732
733        // Create provider.
734        PasspointConfiguration config = new PasspointConfiguration();
735        HomeSP homeSp = new HomeSP();
736        homeSp.setFqdn(fqdn);
737        homeSp.setFriendlyName(friendlyName);
738        homeSp.setRoamingConsortiumOIs(rcOIs);
739        config.setHomeSp(homeSp);
740        Credential credential = new Credential();
741        credential.setRealm(realm);
742        Credential.SimCredential simCredential = new Credential.SimCredential();
743        simCredential.setImsi(imsi);
744        simCredential.setEapType(EAPConstants.EAP_SIM);
745        credential.setSimCredential(simCredential);
746        config.setCredential(credential);
747        mProvider = createProvider(config);
748
749        // Retrieve the WifiConfiguration associated with the provider, and verify the content of
750        // the configuration.  Need to verify field by field since WifiConfiguration doesn't
751        // override equals() function.
752        WifiConfiguration wifiConfig = mProvider.getWifiConfig();
753        WifiEnterpriseConfig wifiEnterpriseConfig = wifiConfig.enterpriseConfig;
754        assertEquals(fqdn, wifiConfig.FQDN);
755        assertEquals(friendlyName, wifiConfig.providerFriendlyName);
756        assertTrue(Arrays.equals(rcOIs, wifiConfig.roamingConsortiumIds));
757        assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
758        assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
759        assertEquals(realm, wifiEnterpriseConfig.getRealm());
760        assertEquals(WifiEnterpriseConfig.Eap.SIM, wifiEnterpriseConfig.getEapMethod());
761        assertEquals(imsi, wifiEnterpriseConfig.getPlmn());
762    }
763}
764