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 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 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 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 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 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 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 184 DefaultSocketFactory() { 185 } 186 187 @Override 188 public Socket createSocket() throws IOException { 189 return new Socket(); 190 } 191 192 @Override 193 public Socket createSocket(String host, int port) throws IOException { 194 return new Socket(host, port); 195 } 196 197 @Override 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 204 public Socket createSocket(InetAddress host, int port) throws IOException { 205 return new Socket(host, port); 206 } 207 208 @Override 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 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 229 public void checkClientTrusted(X509Certificate[] chain, String authType) 230 throws CertificateException { 231 // N/A 232 } 233 234 @Override 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 278 public X509Certificate[] getAcceptedIssuers() { 279 return null; 280 } 281 282 public X509Certificate[] getTrustChain() { 283 return mTrustChain != null ? mTrustChain : new X509Certificate[0]; 284 } 285 } 286 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 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 314 public void init(boolean forward) throws CertPathValidatorException { 315 316 } 317 318 @Override 319 public boolean isForwardCheckingSupported() { 320 return true; 321 } 322 323 @Override 324 public Set<String> getSupportedExtensions() { 325 return EKU_ID_SET; 326 } 327 328 @Override 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