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