• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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