1package de.gultsch.common;
 2
 3import android.content.Context;
 4import android.os.Build;
 5import androidx.annotation.Nullable;
 6import com.google.common.collect.Iterables;
 7import eu.siacs.conversations.R;
 8import java.io.IOException;
 9import java.io.InputStream;
10import java.security.KeyStore;
11import java.security.KeyStoreException;
12import java.security.NoSuchAlgorithmException;
13import java.security.cert.CertificateException;
14import java.util.Arrays;
15import javax.net.ssl.TrustManagerFactory;
16import javax.net.ssl.X509TrustManager;
17
18public final class TrustManagers {
19
20    private static final char[] BUNDLED_KEYSTORE_PASSWORD = "letsencrypt".toCharArray();
21
22    private TrustManagers() {
23        throw new IllegalStateException("Do not instantiate me");
24    }
25
26    public static X509TrustManager createTrustManager(@Nullable final KeyStore keyStore)
27            throws NoSuchAlgorithmException, KeyStoreException {
28        final TrustManagerFactory trustManagerFactory =
29                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
30        trustManagerFactory.init(keyStore);
31        return Iterables.getOnlyElement(
32                Iterables.filter(
33                        Arrays.asList(trustManagerFactory.getTrustManagers()),
34                        X509TrustManager.class));
35    }
36
37    public static X509TrustManager createForAndroidVersion(final Context context)
38            throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException {
39        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
40            return TrustManagers.createDefaultWithBundledLetsEncrypt(context);
41        } else {
42            return TrustManagers.createDefaultTrustManager();
43        }
44    }
45
46    public static X509TrustManager createDefaultTrustManager()
47            throws NoSuchAlgorithmException, KeyStoreException {
48        return createTrustManager(null);
49    }
50
51    private static X509TrustManager createDefaultWithBundledLetsEncrypt(final Context context)
52            throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException {
53        final var bundleTrustManager =
54                createWithKeyStore(context.getResources().openRawResource(R.raw.letsencrypt));
55        return CombiningTrustManager.combineWithDefault(bundleTrustManager);
56    }
57
58    private static X509TrustManager createWithKeyStore(final InputStream inputStream)
59            throws CertificateException, IOException, NoSuchAlgorithmException, KeyStoreException {
60        final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
61        keyStore.load(inputStream, BUNDLED_KEYSTORE_PASSWORD);
62        return TrustManagers.createTrustManager(keyStore);
63    }
64}