1 /*
2  * Copyright 2017 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 android.graphics.drawable.Icon;
20 import android.net.Uri;
21 import android.net.wifi.WifiSsid;
22 import android.net.wifi.hotspot2.OsuProvider;
23 import android.util.Base64;
24 
25 import java.io.ByteArrayInputStream;
26 import java.io.IOException;
27 import java.nio.charset.StandardCharsets;
28 import java.security.KeyStore;
29 import java.security.KeyStoreException;
30 import java.security.NoSuchAlgorithmException;
31 import java.security.cert.Certificate;
32 import java.security.cert.CertificateException;
33 import java.security.cert.CertificateFactory;
34 import java.security.cert.X509Certificate;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40 
41 /**
42  * Helper for creating and populating WifiConfigurations in unit tests.
43  */
44 public class PasspointProvisioningTestUtil {
45     /**
46      * These are constants used to generate predefined OsuProvider.
47      */
48     public static final WifiSsid TEST_SSID =
49             WifiSsid.createFromByteArray("TEST SSID".getBytes(StandardCharsets.UTF_8));
50     public static final String TEST_FRIENDLY_NAME = "Friendly Name";
51     public static final String TEST_SERVICE_DESCRIPTION = "Dummy Service";
52     public static final Uri TEST_SERVER_URI = Uri.parse("https://test.com");
53     public static final Uri INVALID_SERVER_URI = Uri.parse("abcd");
54     public static final String TEST_NAI = "test.access.com";
55     public static final List<Integer> TEST_METHOD_LIST =
56             Arrays.asList(OsuProvider.METHOD_SOAP_XML_SPP);
57     public static final Icon TEST_ICON = Icon.createWithData(new byte[10], 0, 10);
58 
59     /**
60      * Construct a {@link android.net.wifi.hotspot2.OsuProvider}.
61      *
62      * @param openOsuAP indicates if the OSU AP belongs to an open or OSEN network
63      * @return the constructed {@link android.net.wifi.hotspot2.OsuProvider}
64      */
generateOsuProvider(boolean openOsuAP)65     public static OsuProvider generateOsuProvider(boolean openOsuAP) {
66         Map<String, String> friendlyNames = new HashMap<>();
67         friendlyNames.put("en", TEST_FRIENDLY_NAME);
68         return generateOsuProviderWithFriendlyName(openOsuAP, friendlyNames);
69     }
70 
71     /**
72      * Construct a {@link android.net.wifi.hotspot2.OsuProvider} with given friendlyName.
73      *
74      * @param openOsuAP     indicates if the OSU AP belongs to an open or OSEN network
75      * @param friendlyNames map of friendly names with language and friendly name in the language
76      * @return the constructed {@link android.net.wifi.hotspot2.OsuProvider}
77      */
generateOsuProviderWithFriendlyName(boolean openOsuAP, Map<String, String> friendlyNames)78     public static OsuProvider generateOsuProviderWithFriendlyName(boolean openOsuAP,
79             Map<String, String> friendlyNames) {
80         if (openOsuAP) {
81             return new OsuProvider(TEST_SSID, friendlyNames,
82                     TEST_SERVICE_DESCRIPTION,
83                     TEST_SERVER_URI, null, TEST_METHOD_LIST, TEST_ICON);
84         } else {
85             return new OsuProvider(TEST_SSID, friendlyNames,
86                     TEST_SERVICE_DESCRIPTION,
87                     TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST, TEST_ICON);
88         }
89     }
90 
91     /**
92      * Construct a {@link android.net.wifi.hotspot2.OsuProvider} with invalid server URL
93      * @return the constructed {@link android.net.wifi.hotspot2.OsuProvider}
94      */
generateInvalidServerUrlOsuProvider()95     public static OsuProvider generateInvalidServerUrlOsuProvider() {
96         HashMap<String, String> friendlyNameMap = new HashMap<>();
97         friendlyNameMap.put("en", TEST_FRIENDLY_NAME);
98         return new OsuProvider(TEST_SSID, friendlyNameMap,
99                 TEST_SERVICE_DESCRIPTION, INVALID_SERVER_URI, null, TEST_METHOD_LIST, TEST_ICON);
100     }
101 
102     /**
103      * Create the fake keyStore for the test.
104      *
105      * @return KeyStore that has the TEST_CERTs, null if not processed
106      */
createFakeKeyStore()107     public static KeyStore createFakeKeyStore() {
108         KeyStore keyStore = null;
109         int index = 0;
110         try {
111             keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
112             keyStore.load(null, null);
113             List<X509Certificate> certs = getOsuCertsForTest();
114             for (X509Certificate cert : certs) {
115                 keyStore.setCertificateEntry(String.format("%d", index), cert);
116                 index++;
117             }
118         } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException
119                 | IOException e) {
120             e.printStackTrace();
121         }
122         return keyStore;
123     }
124 
125     /**
126      * Return a set of OSU server certs to test with
127      * @return List<X509Certificate> an array of OSU certs
128      */
getOsuCertsForTest()129     /* package */ static List<X509Certificate> getOsuCertsForTest() {
130         List<X509Certificate> osuCerts = new ArrayList<X509Certificate>();
131         try {
132             CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
133             for (String certString : TEST_CERTS) {
134                 ByteArrayInputStream bis = new ByteArrayInputStream(
135                         Base64.decode(certString, Base64.DEFAULT));
136                 Certificate cert = certFactory.generateCertificate(bis);
137                 osuCerts.add((X509Certificate) cert);
138             }
139         } catch (CertificateException e) {
140             e.printStackTrace();
141         }
142         return osuCerts;
143     }
144 
145     private static final String[] TEST_CERTS = {
146             "MIID8zCCAtugAwIBAgIJAIY3yjv1B5eWMA0GCSqGSIb3DQEBCwUAMIGPMQswCQYD"
147                 + "VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxDzAN"
148                 + "BgNVBAoMBkdvb2dsZTEQMA4GA1UECwwHQW5kcm9pZDETMBEGA1UEAwwKZ29vZ2xl"
149                 + "LmNvbTEjMCEGCSqGSIb3DQEJARYUc29oYW5pcmFvQGdvb2dsZS5jb20wHhcNMTgw"
150                 + "MTEyMDM0NjI3WhcNMTkwMTEyMDM0NjI3WjCBjzELMAkGA1UEBhMCVVMxCzAJBgNV"
151                 + "BAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MQ8wDQYDVQQKDAZHb29nbGUx"
152                 + "EDAOBgNVBAsMB0FuZHJvaWQxEzARBgNVBAMMCmdvb2dsZS5jb20xIzAhBgkqhkiG"
153                 + "9w0BCQEWFHNvaGFuaXJhb0Bnb29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC"
154                 + "AQ8AMIIBCgKCAQEA41IIl6NpaN60XbS/fb0bW8+nWGh8OrHjFTyEOSXAE9W+sxFi"
155                 + "x2ygJxJvOpN0Nj+UFXMDnwIkvq7l0L0kUTAljQh1C1Gm4a2rDYKkMhTNab5uSp1/"
156                 + "X3VDUztIJVn4EKIt5jT9vGTqwvI4Xxd3fmM1/eRHpzR8gRLLs89itulpoHrXiN29"
157                 + "dlD72J2877vo3QktFMo/MiHyWPne5WiU5+qiAw70MflnptzaOCeisCVSYHyvhDtK"
158                 + "xWPgQ9eqG1jHgxOgdOEB6nzJvWY26GzjpEVZlUOBeEvcznmTqrFoM4Q4ANX//F1+"
159                 + "zdNfQPes5fPShMgLp65MAdVJFQKq7o8jVcX+2wIDAQABo1AwTjAdBgNVHQ4EFgQU"
160                 + "467KG5Zzpr4nnURUbOwdr5hoQVkwHwYDVR0jBBgwFoAU467KG5Zzpr4nnURUbOwd"
161                 + "r5hoQVkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAvI9DKIXTrJQi"
162                 + "Gaobr0wnQ1JfpP3oezWHmhFDSwdq3xhFLlxlZOLi3Ay/GwaW3cQfQ8c6xzpbjVNm"
163                 + "uMyNzfVHZjzRoX7Ae9S0uzsYmXuAm3LbD4EDflDDHlYKz97J4nlzPvi/EUxoOmk0"
164                 + "CF2LS9CAsI/AVCOqXne89EK4TwsZ8fSzNv0I2YdA2VFHUqqW2h1uZCG9Mb4gmwGj"
165                 + "bjxrdFAKFlSKxUfrus+BGwjOKwfvvkWLmU4TPqBAPgVLHUBrcdDoIoYW6XAA4Dnd"
166                 + "4eMFTUDmMaUew8K5aGuuj+2fNcOuz+/wy2xL8TkGF/m1Xi1JUbk0Ny/pG3qaznzB"
167                 + "FeODMMYDCg==",
168 
169         "MIIC7jCCAdagAwIBAgIJAI0gOVoxJv+kMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNV"
170                 + "BAMTC2RvbWFpbjEuY29tMB4XDTE4MDExMzAwMzczOFoXDTE4MDIxMjAwMzczOFow"
171                 + "FjEUMBIGA1UEAxMLZG9tYWluMS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw"
172                 + "ggEKAoIBAQDsIvx1z9iLMuXXjP2/9YEBAMCQ6qC75t5YmqZeCfl2SIjt3Ho2qCRA"
173                 + "Wq5y5ZTSqTTBTMMiDHGAYe+qcP7+4UuyCx60CbhJVn1Maxcrhs3tUEKJlQNqEk4t"
174                 + "I4DONvZjsOX1UxYNvbjMlWf3KZ0rXLusvMjk4VEOxZVvyO4EyJ+K4tMse7OkHBGt"
175                 + "eBATgOqFvOZxy3SaicH36bN5eL6KWHOe0IIGoQ4VLcMrW9hBwSBaO9m95I0ZNAqt"
176                 + "0+84hgJNna6KtPRGfPaHdJfYZ6yqWMtpUr9yz8GRlSY67vieFkB+Qx2WO/En2K25"
177                 + "PM/zVGqmNFpDeATbUmCUDWegNb4XPkJBAgMBAAGjPzA9MAsGA1UdDwQEAwIEMDAT"
178                 + "BgNVHSUEDDAKBggrBgEFBQcDATAZBgNVHREEEjAQgg53d3cuZ29vZ2xlLmNvbTAN"
179                 + "BgkqhkiG9w0BAQsFAAOCAQEAQX+HT2JlCnZ/Zb9hCe8139poDxqkj4ZhYu94OpLH"
180                 + "Y+eRsMY8SA/rHp0fbCiqA4H/IL9GI79HGdcjNChqVH304fvdic97dwXZLOFC/JcO"
181                 + "XXIZs/j1ir6WfezhTdrLHXB+ZYahST2L8fEHeyS+goZFK0XNgdvTe1h2W7qfdn3Z"
182                 + "G4DkdYhFlzXnvSq+YI2SvSArrbw02wg4xZzHwXHsV8sIXuve8KvZzKw0+zP2oj5b"
183                 + "XgkNgi75VBf+dEvA9D6GSJ9uNaUmhlglpiwyeMBhDGYibje1/e4aQYclaarWMkf2"
184                 + "IYatpc/KqB9TWGIAVGLsCcfDbdbIil2AlaoA006SXa1fHA=="
185     };
186 }
187