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