1 package com.android.hotspot2.osu; 2 3 import android.net.Network; 4 import android.util.Base64; 5 import android.util.Log; 6 7 import com.android.hotspot2.Utils; 8 import com.android.hotspot2.pps.HomeSP; 9 10 import java.io.ByteArrayInputStream; 11 import java.io.IOException; 12 import java.net.InetAddress; 13 import java.net.InetSocketAddress; 14 import java.net.Socket; 15 import java.net.URL; 16 import java.security.GeneralSecurityException; 17 import java.security.KeyStore; 18 import java.security.KeyStoreException; 19 import java.security.PrivateKey; 20 import java.security.cert.CertPath; 21 import java.security.cert.CertPathValidator; 22 import java.security.cert.CertPathValidatorException; 23 import java.security.cert.Certificate; 24 import java.security.cert.CertificateException; 25 import java.security.cert.CertificateFactory; 26 import java.security.cert.PKIXCertPathChecker; 27 import java.security.cert.PKIXParameters; 28 import java.security.cert.TrustAnchor; 29 import java.security.cert.X509Certificate; 30 import java.util.ArrayList; 31 import java.util.Arrays; 32 import java.util.Collection; 33 import java.util.Collections; 34 import java.util.HashSet; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.Set; 38 39 import javax.net.SocketFactory; 40 import javax.net.ssl.KeyManager; 41 import javax.net.ssl.SSLContext; 42 import javax.net.ssl.TrustManager; 43 import javax.net.ssl.X509TrustManager; 44 45 public class OSUSocketFactory { 46 private static final long ConnectionTimeout = 10000L; 47 private static final long ReconnectWait = 2000L; 48 49 private static final String SecureHTTP = "https"; 50 private static final String UnsecureHTTP = "http"; 51 private static final String EKU_ID = "2.5.29.37"; 52 private static final Set<String> EKU_ID_SET = new HashSet<>(Arrays.asList(EKU_ID)); 53 private static final EKUChecker sEKUChecker = new EKUChecker(); 54 55 private final Network mNetwork; 56 private final SocketFactory mSocketFactory; 57 private final KeyManager mKeyManager; 58 private final WFATrustManager mTrustManager; 59 private final List<InetSocketAddress> mRemotes; 60 buildCertSet()61 public static Set<X509Certificate> buildCertSet() { 62 try { 63 CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 64 Set<X509Certificate> set = new HashSet<>(); 65 for (String b64 : WFACerts) { 66 ByteArrayInputStream bis = new ByteArrayInputStream( 67 Base64.decode(b64, Base64.DEFAULT)); 68 X509Certificate cert = (X509Certificate) certFactory.generateCertificate(bis); 69 set.add(cert); 70 } 71 return set; 72 } catch (CertificateException ce) { 73 Log.e(OSUManager.TAG, "Cannot build CA cert set"); 74 return null; 75 } 76 } 77 getSocketFactory(KeyStore ks, HomeSP homeSP, int flowType, Network network, URL url, KeyManager km, boolean enforceSecurity)78 public static OSUSocketFactory getSocketFactory(KeyStore ks, HomeSP homeSP, int flowType, 79 Network network, URL url, KeyManager km, 80 boolean enforceSecurity) 81 throws GeneralSecurityException, IOException { 82 83 if (enforceSecurity && !url.getProtocol().equalsIgnoreCase(SecureHTTP)) { 84 throw new IOException("Protocol '" + url.getProtocol() + "' is not secure"); 85 } 86 return new OSUSocketFactory(ks, homeSP, flowType, network, url, km); 87 } 88 OSUSocketFactory(KeyStore ks, HomeSP homeSP, int flowType, Network network, URL url, KeyManager km)89 private OSUSocketFactory(KeyStore ks, HomeSP homeSP, int flowType, Network network, 90 URL url, KeyManager km) throws GeneralSecurityException, IOException { 91 mNetwork = network; 92 mKeyManager = km; 93 mTrustManager = new WFATrustManager(ks, homeSP, flowType); 94 int port; 95 switch (url.getProtocol()) { 96 case UnsecureHTTP: 97 mSocketFactory = new DefaultSocketFactory(); 98 port = url.getPort() > 0 ? url.getPort() : 80; 99 break; 100 case SecureHTTP: 101 SSLContext tlsContext = SSLContext.getInstance("TLSv1"); 102 tlsContext.init(km != null ? new KeyManager[]{km} : null, 103 new TrustManager[]{mTrustManager}, null); 104 mSocketFactory = tlsContext.getSocketFactory(); 105 port = url.getPort() > 0 ? url.getPort() : 443; 106 break; 107 default: 108 throw new IOException("Bad URL: " + url); 109 } 110 if (OSUManager.R2_MOCK && url.getHost().endsWith(".wi-fi.org")) { 111 // !!! Warning: Ruckus hack! 112 mRemotes = new ArrayList<>(1); 113 mRemotes.add(new InetSocketAddress(InetAddress.getByName("10.123.107.107"), port)); 114 } else { 115 InetAddress[] remotes = mNetwork.getAllByName(url.getHost()); 116 android.util.Log.d(OSUManager.TAG, "'" + url.getHost() + "' resolves to " + 117 Arrays.toString(remotes)); 118 if (remotes == null || remotes.length == 0) { 119 throw new IOException("Failed to look up host from " + url); 120 } 121 mRemotes = new ArrayList<>(remotes.length); 122 for (InetAddress remote : remotes) { 123 mRemotes.add(new InetSocketAddress(remote, port)); 124 } 125 } 126 Collections.shuffle(mRemotes); 127 } 128 reloadKeys(Map<OSUCertType, List<X509Certificate>> certs, PrivateKey key)129 public void reloadKeys(Map<OSUCertType, List<X509Certificate>> certs, PrivateKey key) 130 throws IOException { 131 if (mKeyManager instanceof ClientKeyManager) { 132 ((ClientKeyManager) mKeyManager).reloadKeys(certs, key); 133 } 134 } 135 createSocket()136 public Socket createSocket() throws IOException { 137 Socket socket = mSocketFactory.createSocket(); 138 mNetwork.bindSocket(socket); 139 140 long bail = System.currentTimeMillis() + ConnectionTimeout; 141 boolean success = false; 142 143 while (System.currentTimeMillis() < bail) { 144 for (InetSocketAddress remote : mRemotes) { 145 try { 146 socket.connect(remote); 147 Log.d(OSUManager.TAG, "Connection " + socket.getLocalSocketAddress() + 148 " to " + socket.getRemoteSocketAddress()); 149 success = true; 150 break; 151 } catch (IOException ioe) { 152 Log.d(OSUManager.TAG, "Failed to connect to " + remote + ": " + ioe); 153 socket = mSocketFactory.createSocket(); 154 mNetwork.bindSocket(socket); 155 } 156 } 157 if (success) { 158 break; 159 } 160 Utils.delay(ReconnectWait); 161 } 162 if (!success) { 163 throw new IOException("No available network"); 164 } 165 return socket; 166 } 167 getOSUCertificate(URL url)168 public X509Certificate getOSUCertificate(URL url) throws GeneralSecurityException { 169 String fqdn = url.getHost(); 170 for (X509Certificate certificate : mTrustManager.getTrustChain()) { 171 for (List<?> name : certificate.getSubjectAlternativeNames()) { 172 if (name.size() >= SPVerifier.DNSName && 173 name.get(0).getClass() == Integer.class && 174 name.get(1).toString().equals(fqdn)) { 175 return certificate; 176 } 177 } 178 } 179 return null; 180 } 181 182 final class DefaultSocketFactory extends SocketFactory { 183 DefaultSocketFactory()184 DefaultSocketFactory() { 185 } 186 187 @Override createSocket()188 public Socket createSocket() throws IOException { 189 return new Socket(); 190 } 191 192 @Override createSocket(String host, int port)193 public Socket createSocket(String host, int port) throws IOException { 194 return new Socket(host, port); 195 } 196 197 @Override createSocket(String host, int port, InetAddress localHost, int localPort)198 public Socket createSocket(String host, int port, InetAddress localHost, int localPort) 199 throws IOException { 200 return new Socket(host, port, localHost, localPort); 201 } 202 203 @Override createSocket(InetAddress host, int port)204 public Socket createSocket(InetAddress host, int port) throws IOException { 205 return new Socket(host, port); 206 } 207 208 @Override createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)209 public Socket createSocket(InetAddress address, int port, InetAddress localAddress, 210 int localPort) throws IOException { 211 return new Socket(address, port, localAddress, localPort); 212 } 213 } 214 215 private static class WFATrustManager implements X509TrustManager { 216 private final KeyStore mKeyStore; 217 private final HomeSP mHomeSP; 218 private final int mFlowType; 219 private X509Certificate[] mTrustChain; 220 WFATrustManager(KeyStore ks, HomeSP homeSP, int flowType)221 private WFATrustManager(KeyStore ks, HomeSP homeSP, int flowType) 222 throws CertificateException { 223 mKeyStore = ks; 224 mHomeSP = homeSP; 225 mFlowType = flowType; 226 } 227 228 @Override checkClientTrusted(X509Certificate[] chain, String authType)229 public void checkClientTrusted(X509Certificate[] chain, String authType) 230 throws CertificateException { 231 // N/A 232 } 233 234 @Override checkServerTrusted(X509Certificate[] chain, String authType)235 public void checkServerTrusted(X509Certificate[] chain, String authType) 236 throws CertificateException { 237 Log.d("TLSOSU", "Checking " + chain.length + " certs."); 238 239 try { 240 CertPathValidator validator = 241 CertPathValidator.getInstance(CertPathValidator.getDefaultType()); 242 CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 243 CertPath path = certFactory.generateCertPath( 244 Arrays.asList(chain)); 245 Set<TrustAnchor> trustAnchors = new HashSet<>(); 246 if (mHomeSP == null) { 247 for (X509Certificate cert : getRootCerts(mKeyStore)) { 248 trustAnchors.add(new TrustAnchor(cert, null)); 249 } 250 } else { 251 String prefix = mFlowType == OSUManager.FLOW_REMEDIATION ? 252 OSUManager.CERT_REM_ALIAS : OSUManager.CERT_POLICY_ALIAS; 253 254 X509Certificate cert = getCert(mKeyStore, prefix + mHomeSP.getFQDN()); 255 if (cert == null) { 256 cert = getCert(mKeyStore, OSUManager.CERT_SHARED_ALIAS + mHomeSP.getFQDN()); 257 } 258 if (cert == null) { 259 for (X509Certificate root : getRootCerts(mKeyStore)) { 260 trustAnchors.add(new TrustAnchor(root, null)); 261 } 262 } else { 263 trustAnchors.add(new TrustAnchor(cert, null)); 264 } 265 } 266 PKIXParameters params = new PKIXParameters(trustAnchors); 267 params.setRevocationEnabled(false); 268 params.addCertPathChecker(sEKUChecker); 269 validator.validate(path, params); 270 mTrustChain = chain; 271 } catch (GeneralSecurityException gse) { 272 throw new SecurityException(gse); 273 } 274 mTrustChain = chain; 275 } 276 277 @Override getAcceptedIssuers()278 public X509Certificate[] getAcceptedIssuers() { 279 return null; 280 } 281 getTrustChain()282 public X509Certificate[] getTrustChain() { 283 return mTrustChain != null ? mTrustChain : new X509Certificate[0]; 284 } 285 } 286 getCert(KeyStore keyStore, String alias)287 private static X509Certificate getCert(KeyStore keyStore, String alias) 288 throws KeyStoreException { 289 Certificate cert = keyStore.getCertificate(alias); 290 if (cert != null && cert instanceof X509Certificate) { 291 return (X509Certificate) cert; 292 } 293 return null; 294 } 295 getRootCerts(KeyStore keyStore)296 public static Set<X509Certificate> getRootCerts(KeyStore keyStore) throws KeyStoreException { 297 Set<X509Certificate> certSet = new HashSet<>(); 298 int index = 0; 299 for (int n = 0; n < 1000; n++) { 300 Certificate cert = keyStore.getCertificate( 301 String.format("%s%d", OSUManager.CERT_WFA_ALIAS, index)); 302 if (cert == null) { 303 break; 304 } else if (cert instanceof X509Certificate) { 305 certSet.add((X509Certificate) cert); 306 } 307 index++; 308 } 309 return certSet; 310 } 311 312 private static class EKUChecker extends PKIXCertPathChecker { 313 @Override init(boolean forward)314 public void init(boolean forward) throws CertPathValidatorException { 315 316 } 317 318 @Override isForwardCheckingSupported()319 public boolean isForwardCheckingSupported() { 320 return true; 321 } 322 323 @Override getSupportedExtensions()324 public Set<String> getSupportedExtensions() { 325 return EKU_ID_SET; 326 } 327 328 @Override check(Certificate cert, Collection<String> unresolvedCritExts)329 public void check(Certificate cert, Collection<String> unresolvedCritExts) 330 throws CertPathValidatorException { 331 Log.d(OSUManager.TAG, "Checking EKU " + unresolvedCritExts); 332 unresolvedCritExts.remove(EKU_ID); 333 } 334 } 335 336 /* 337 * 338 Subject: CN=osu-server.r2-testbed-rks.wi-fi.org, O=Intel Corporation CCG DRD, C=US 339 Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11 340 Validity: [From: Wed Jan 28 16:00:00 PST 2015, 341 To: Sat Jan 28 15:59:59 PST 2017] 342 Issuer: CN="NetworkFX, Inc. Hotspot 2.0 Intermediate CA", OU=OSU CA - 01, O="NetworkFX, Inc.", C=US 343 SerialNumber: [ 312af3db 138eae19 1defbce2 e2b88b55] 344 * 345 * 346 Subject: CN="NetworkFX, Inc. Hotspot 2.0 Intermediate CA", OU=OSU CA - 01, O="NetworkFX, Inc.", C=US 347 Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11 348 Validity: [From: Tue Nov 19 16:00:00 PST 2013, 349 To: Sun Nov 19 15:59:59 PST 2023] 350 Issuer: CN=Hotspot 2.0 Trust Root CA - 01, O=WFA Hotspot 2.0, C=US 351 SerialNumber: [ 4152b1b0 301495f3 8fa76428 2ef41046] 352 */ 353 354 public static final String[] WFACerts = { 355 "MIIFbDCCA1SgAwIBAgIQDLMPcPKGpDPguQmJ3gHttzANBgkqhkiG9w0BAQsFADBQ" + 356 "MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPV0ZBIEhvdHNwb3QgMi4wMScwJQYDVQQD" + 357 "Ex5Ib3RzcG90IDIuMCBUcnVzdCBSb290IENBIC0gMDMwHhcNMTMxMjA4MTIwMDAw" + 358 "WhcNNDMxMjA4MTIwMDAwWjBQMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPV0ZBIEhv" + 359 "dHNwb3QgMi4wMScwJQYDVQQDEx5Ib3RzcG90IDIuMCBUcnVzdCBSb290IENBIC0g" + 360 "MDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsdEtReIUbMlO+hR6b" + 361 "yQk4nGVITv3meYTaDeVwZnQVal8EjHuu4Kd89g8yRYVTv3J1kq9ukE7CDrDehrXK" + 362 "ym+8VlR7ro0lB/lwRyNk3W7yNccg3AknQ0x5fKVwcFznwD/FYg37owGmhGFtpMTB" + 363 "cxzreQaLXvLta8YNlJU10ZkfputBpzi9bLPWsLOkIrQw7KH1Wc+Oiy4hUMUbTlSi" + 364 "cjqacKPR188mVIoxxUoICHyVV1KvMmYZrVdc/b5dbmd0haMHxC0VSqbydXxxS7vv" + 365 "/lCrC2d5qbKE66PiuBPkhzyU7SI9C8GU/S7akYm1MMSTn5W7lSp2AWRDnf9LQg51" + 366 "dLvDxJ7t2fruXtSkkqG/cwY1yQI8O+WZYPDThKPcDmNbaxVE9lOizAHXFVsfYrXA" + 367 "PbbMOkzKehYwaIikmNgcpxtQNw+wikJiZb9N8VwwtwHK71XEFi+n5DGlPa9VDYgB" + 368 "YkBcxvVo2rbE3i3teQgHm+pWZNP08aFNWwMk9yQkm/SOGdLq1jLbQA9yd7fyR1Ct" + 369 "W1GLzKi1Ojr/6XiB9/noL3oxP/+gb8OSgcqVfkZp4QLvrGdlKiOI2fE7Bslmzn6l" + 370 "B3UTpApjab7BQ99rCXzDwt3Xd7IrCtAJNkxi302J7k6hnGlW8S4oPQBElkOtoH9y" + 371 "XEhp9rNS0lZiuwtFmWW2q50fkQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G" + 372 "A1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUZw5JLGEXnuvt4FTnhNmbrWRgc2UwDQYJ" + 373 "KoZIhvcNAQELBQADggIBAFPoGFDyzFg9B9+jJUPGW32omftBhChVcgjllI07RCie" + 374 "KTMBi47+auuLgiMox3xRyP7/dX7YaUeMXEQ1BMv6nlrsXWv1lH4yu+RNuehPlqRs" + 375 "fY351mAfPtQ654SBUi0Wg++9iyTOfgF5a9IWEDt4lnSZMvA4vlw8pUCz6zpKXHnA" + 376 "RXKrpY3bU+2dnrFDKR0XQhmAQdo7UvdsT1elVoFIxHhLpwfzx+kpEhtrXw3nGgt+" + 377 "M4jNp684XoWpxVGaQ4Vvv00Sm2DQ8jq2sf9F+kRWszZpQOTiMGKZr0lX2CI5cww1" + 378 "dfmd1BkAjI9cIWLkD8YSeaggZzvYe1o9d7e7lKfdJmjDlSQ0uBiG77keUK4tF2fi" + 379 "xFTxibtPux56p3GYQ2GdRsBaKjH3A3HMJSKXwIGR+wb1sgz/bBdlyJSylG8hYD//" + 380 "0Hyo+UrMUszAdszoPhMY+4Ol3QE3QRWzXi+W/NtKeYD2K8xUzjZM10wMdxCfoFOa" + 381 "8bzzWnxZQlnu880ULUSHIxDPeE+DDZYYOaN1hV2Rh/hrFKvvV+gJj2eXHF5G7y9u" + 382 "Yg7nHYCCf7Hy8UTIXDtAAeDCQNon1ReN8G+XOqhLQ9TalmnJ5U5ARtC0MdQDht7T" + 383 "DZpWeEVv+pQHARX9GDV/T85MV2RPJWKqfZ6kK0gvQDkunADdg8IhZAjwMMx3k6B/", 384 385 "MIIFbDCCA1SgAwIBAgIQaAV8NQv/Xdusi4IU+tpUfjANBgkqhkiG9w0BAQsFADBQ" + 386 "MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPV0ZBIEhvdHNwb3QgMi4wMScwJQYDVQQD" + 387 "Ex5Ib3RzcG90IDIuMCBUcnVzdCBSb290IENBIC0gMDEwHhcNMTMxMTIwMDAwMDAw" + 388 "WhcNNDMxMTE5MjM1OTU5WjBQMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPV0ZBIEhv" + 389 "dHNwb3QgMi4wMScwJQYDVQQDEx5Ib3RzcG90IDIuMCBUcnVzdCBSb290IENBIC0g" + 390 "MDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/gf4CHxWjr2EcktAZ" + 391 "pHT4z1yFYZILD3ZVqvzzXBK+YKjWhjsgZ28Z1VwXqu51JvVzwTGDalPf5m7zMcJW" + 392 "CpPtPBdxxwQ/cBDPK4w+/sCuYYSddlMLzwZ/IgwFike12tKTR7Kk7Nk6ghrYaxCG" + 393 "R+QEZDVrxITj79vGpgk2otVnMI4d3H9mWt1o6Lx+hVioyBgOvmo2OWHR2uKkbg5h" + 394 "tktXqmBEtzK+qDqIIUY4WRRZHxlOaF2/EdIIGhXlf+Vlr13aPqOPiDiE08o+GARz" + 395 "TIp8BrW2boo0+2kpEFUKiqc427vOYEkUdSMfwu4aGOcuOewc8sk6ztquL/JcPROL" + 396 "VSFSSFR3HKhUto8EJcHEEG9wzcOi1OO/OOSVxjNwiaV/hB9Ed1wvoBhiJ+C+Q8/K" + 397 "HXmoH/ankXDaB06yjt2Ojemt0nO45qlarRj8tO7zbpghJuJxztur47U7PJta7Zcg" + 398 "z7kOPJPTAbzmOU2TXt1pXO1hVnSlV+M1rRwe7qivnSMMrTnkX15YWmyK27/tgJeu" + 399 "muR2YzvPwPtF/m1N0bRKI7FW05NYg3smItFq0E/eyf/orgolcXTZ7zNRyRGnjWNs" + 400 "/w9SDbdby0uVUfdN4V/5uC4HBmA1rikoBbGZ+nzCtesY4yW8eEwMfguVpNT3ueaU" + 401 "q30nufeY2VnA3Rv1WH8TaeZU+wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G" + 402 "A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU+RjGVZbebjpzEPfthaTLqbvXMiEwDQYJ" + 403 "KoZIhvcNAQELBQADggIBABj3LP1UXVa16HYeXC1+GU1dX/cla1n1bwpIlxRnCZ5/" + 404 "3I3zGw/nRnsLUTkGf8q3XCgin+jX22kyzzQNrgepn0zqBsmAj+pjUUwWzYQUzphc" + 405 "Uzmg4PJRWaEaGG3kvD+wJEC0pWvIhe48qcq8FZCCmjbvecEVn5mM0smPzPyUjf/o" + 406 "fjUMQvVWqug/Ff5HT6kbyDWhC3nD+8IZ5PjyO85OnoBnQkr8WYwr24XJgO2HS2rs" + 407 "W40CzQe3Kdg7HHyef+/iyLYTBJH7EUJPCHGVQtZ3q0aNqURkutXJ/CxKJYMcNTEB" + 408 "x+a09EhZ6DOHQDqsdTuAqGh3VyrxhFk+3suNsxoh6XaRK10VslvdNB/1YKfU8DWe" + 409 "V6XfDH/TR0NIL04exUp3rER8sERulpJGBOnaG6OQKh4bFYDB406+QfusQnvO0aYR" + 410 "UXJzf01B15HRJgpZsggpIuex0UDcJhTTpkRfTj8L4ayUce2ZRsGn3dBaT9ZMx4o9" + 411 "E/YsQyOpfw28gM5u+zZt4BJz4gAaRGbp4r4sk5Vm/P1/0EXJ70Du6K9d0HAHtpEv" + 412 "Y94Ww5W6fpMDdyAKYTXZBgTX3cqtikNkLX/kHH8l4o/XW2sXqU3X7vOYqgeVYoD9" + 413 "NnhZXYCerH4Se5Lgj8/KhXxRWtcn3XduMdkC6UTApMooA64Vs508173Z3lJn2SeQ", 414 415 "MIIFXTCCA0WgAwIBAgIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEY" + 416 "MBYGA1UECgwPV0ZBIEhvdHNwb3QgMi4wMScwJQYDVQQDDB5Ib3RzcG90IDIuMCBU" + 417 "cnVzdCBSb290IENBIC0gMDIwHhcNMTMxMjAyMjA1NzU3WhcNNDMxMjAyMjA1NTAz" + 418 "WjBQMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPV0ZBIEhvdHNwb3QgMi4wMScwJQYD" + 419 "VQQDDB5Ib3RzcG90IDIuMCBUcnVzdCBSb290IENBIC0gMDIwggIiMA0GCSqGSIb3" + 420 "DQEBAQUAA4ICDwAwggIKAoICAQDCSoMqNhtTwbnIsINp6nUhx5UFuq9ZQoTv+KDk" + 421 "vAajT0di6+cQG3sAVvZLySmJoiBAv3PizYYLOD4eGMrFQRqi7PmSJ83WqNv23ZYF" + 422 "ryFFJiy/URXc/ALDuB3dgElPt24Mx7n2xDPAh9t82HTmuskpQRrsyg9QPoi5rRRS" + 423 "Djm5mjFJjKChq99RWcweNV/KGH1sTwcmlDmNMScK16A+BBNiSvmZlsGJgAlP369k" + 424 "lnNqt6UiDhepcktuKpHmSvNel+c/xqzR0gURfUnXcZhzjzS94Rx5O+CNWL4EGiJq" + 425 "qKAfk99j/lbD0MWYo7Rh0UKQlXSdohWDiV93hxvvfugej8KUOIb+1wmd1Fi+lwDZ" + 426 "bR2yg2f0qyxbC/tAV4JJNnuDLFb19leD78x+68eAnlbMi+xMH5lINs15+26s2H5d" + 427 "lx9kwRDBJq02LuHnen6FLafWjejnnBQ/PuGD0ACvBegSsDKDaCuTAnTNS6MDmQr4" + 428 "wza08iX360ZN+BbSAnCK1YGa/7J7fhyydwxLJ7s5Eo0b6SUMY87FMc5XmkAk4xxL" + 429 "MLqS2HMtqsGBI5JQT0SgH0ghE6DjMWArBTZcD+swuzTi1/Cz5+Z9Es8xJ3MPvSZW" + 430 "pJi6VVB2eVMAqfHOj4ozHoVpvJypIVGRwWBzVRWom76R47utuRK6uKzoLiB1jwE5" + 431 "vwHpUQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBxjAd" + 432 "BgNVHQ4EFgQU5C9c1OMsB+/MOwl9OKG2D/XSwrUwDQYJKoZIhvcNAQELBQADggIB" + 433 "AGULYE/VrnA3K0ptgHrWlQoPfp5wGvScgsmy0wp9qE3b6n/4bLehBKb5w4Y3JVA9" + 434 "gjxoQ5xE2ssDtULZ3nKnGWmMN3qOBoRZCA6KjKs1860p09tm1ScUsajDJ15Tp1nI" + 435 "zfR0oP63+2bJx+JXM8fPKOJe245hj2rs1c3JXsGCe+UVrlGsotG+wR0PdrejaXJ8" + 436 "HbhBQHcbhgjsD1Gb6Egm4YxRKAtcVY3q9EKKWAGhbC1qvCh1iLNKo3FeGgm2r3EG" + 437 "L4cYJBb2fhSKltjISqCDhYq4tplOIeQSJJyJC8gfW/BnMU39lTjNgnSjjGPLQXGV" + 438 "+Ulb/CgNMJ3RhRJdBoLcpIm/EeLx6JLq/2Erxy7CxjaSOcD0UKa14+dzLSHVsXft" + 439 "HZuOy548X8m18KruSZsf5uAT3c7NqlXtr9YgOVUqSJykNAHTGi/BHB1dC2clKvxN" + 440 "ElfLWWrG9yaAd5TFW0+3wsaDIwRZL584AsFwwAD3KMo1oU/2zRvtm0E+VghsuD/Z" + 441 "IE1xaVGTPaL7ph/YgC9+0rGHieauT8SXz6Ryp3h0RtYMLFZOMTKM7xjmcbMZDwrO" + 442 "c+J/XjK9dbiCqlx5/B8P0xWaYYHzvE5/fafiPYzoGyFVUXquu0dFCCQrvjF/y0tC" + 443 "TPm4hQim3k1F+5NChcbeNggN+kq+VdlSqPhQEuOY+kNv" 444 }; 445 446 //private static final Set<TrustAnchor> sTrustAnchors = buildCertSet(); 447 } 448