All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.jsse.provider.ProvTrustManagerFactorySpi Maven / Gradle / Ivy

Go to download

The Bouncy Castle Java APIs for the TLS, including a JSSE provider. The APIs are designed primarily to be used in conjunction with the BC FIPS provider. The APIs may also be used with other providers although if being used in a FIPS context it is the responsibility of the user to ensure that any other providers used are FIPS certified and used appropriately.

There is a newer version: 2.0.19
Show newest version
package org.bouncycastle.jsse.provider;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchProviderException;
import java.security.cert.CertPathParameters;
import java.security.cert.Certificate;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.net.ssl.CertPathTrustManagerParameters;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactorySpi;

import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.tls.TlsUtils;

class ProvTrustManagerFactorySpi
    extends TrustManagerFactorySpi
{
    private static final Logger LOG = Logger.getLogger(ProvTrustManagerFactorySpi.class.getName());

    private static final boolean provKeyStoreTypeCompat = PropertyUtils
        .getBooleanSecurityProperty("keystore.type.compat", false);

    static KeyStore getDefaultTrustStore() throws Exception
    {
        String defaultType = KeyStore.getDefaultType();

        boolean defaultCacertsToJKS = provKeyStoreTypeCompat && "pkcs12".equalsIgnoreCase(defaultType);

        String tsPath = null;
        char[] tsPassword = null;

        String tsPathProp = PropertyUtils.getStringSystemProperty("javax.net.ssl.trustStore");
        if ("NONE".equals(tsPathProp))
        {
            // Do not try to load any file
        }
        else if (null != tsPathProp)
        {
            if (new File(tsPathProp).exists())
            {
                tsPath = tsPathProp;
            }
        }
        else
        {
            String javaHome = PropertyUtils.getStringSystemProperty("java.home");
            if (null != javaHome)
            {
                String jsseCacertsPath = javaHome + "/lib/security/jssecacerts".replace("/", File.separator);
                if (new File(jsseCacertsPath).exists())
                {
                    if (defaultCacertsToJKS)
                    {
                        defaultType = "jks";
                    }
                    tsPath = jsseCacertsPath;
                }
                else
                {
                    String cacertsPath = javaHome + "/lib/security/cacerts".replace("/", File.separator);
                    if (new File(cacertsPath).exists())
                    {
                        if (defaultCacertsToJKS)
                        {
                            defaultType = "jks";
                        }
                        tsPath = cacertsPath;
                    }
                }
            }
        }

        KeyStore ks = createTrustStore(defaultType);

        String tsPasswordProp = PropertyUtils.getSensitiveStringSystemProperty("javax.net.ssl.trustStorePassword");
        if (null != tsPasswordProp)
        {
            tsPassword = tsPasswordProp.toCharArray();
        }

        InputStream tsInput = null;
        try
        {
            if (null == tsPath)
            {
                LOG.config("Initializing default trust store as empty");
            }
            else
            {
                LOG.config("Initializing default trust store from path: " + tsPath);
                tsInput = new BufferedInputStream(new FileInputStream(tsPath));
            }

            try
            {
                ks.load(tsInput, tsPassword);
            }
            catch (NullPointerException e)
            {
                // work around for NPE in FIPS KeyStore
                ks = KeyStore.getInstance("BCFKS");
                ks.load(null, null);
            }
        }
        finally
        {
            if (null != tsInput)
            {
                tsInput.close();
            }
        }

        return ks;
    }

    protected final boolean isInFipsMode;
    protected final JcaJceHelper helper;

    protected ProvX509TrustManager x509TrustManager;

    ProvTrustManagerFactorySpi(boolean isInFipsMode, JcaJceHelper helper)
    {
        this.isInFipsMode = isInFipsMode;
        this.helper = helper;
    }

    @Override
    protected TrustManager[] engineGetTrustManagers()
    {
        if (null == x509TrustManager)
        {
            throw new IllegalStateException("TrustManagerFactory not initialized");
        }

        return new TrustManager[]{ x509TrustManager.getExportX509TrustManager() };
    }

    @Override
    protected void engineInit(KeyStore ks)
        throws KeyStoreException
    {
        if (null == ks)
        {
            try
            {
                ks = getDefaultTrustStore();
            }
            catch (SecurityException e)
            {
                LOG.log(Level.WARNING, "Skipped default trust store", e);
                // Ignore
            }
            catch (Error e)
            {
                LOG.log(Level.WARNING, "Skipped default trust store", e);
                throw e;
            }
            catch (RuntimeException e)
            {
                LOG.log(Level.WARNING, "Skipped default trust store", e);
                throw e;
            }
            catch (Exception e)
            {
                LOG.log(Level.WARNING, "Skipped default trust store", e);
                throw new KeyStoreException("Failed to load default trust store", e);
            }
        }

        Set trustAnchors = getTrustAnchors(ks);

        try
        {
            this.x509TrustManager = new ProvX509TrustManager(isInFipsMode, helper, trustAnchors);
        }
        catch (InvalidAlgorithmParameterException e)
        {
            throw new KeyStoreException("Failed to create trust manager", e);
        }
    }

    @Override
    protected void engineInit(ManagerFactoryParameters spec)
        throws InvalidAlgorithmParameterException
    {
        if (spec instanceof CertPathTrustManagerParameters)
        {
            CertPathParameters certPathParameters = ((CertPathTrustManagerParameters)spec).getParameters();
            if (!(certPathParameters instanceof PKIXParameters))
            {
                throw new InvalidAlgorithmParameterException("parameters must inherit from PKIXParameters");
            }

            this.x509TrustManager = new ProvX509TrustManager(isInFipsMode, helper, (PKIXParameters)certPathParameters);
        }
        else if (null == spec)
        {
            throw new InvalidAlgorithmParameterException("spec cannot be null");
        }
        else
        {
            throw new InvalidAlgorithmParameterException("unknown spec: " + spec.getClass().getName());
        }
    }

    private static void collectTrustAnchor(Set trustAnchors, Certificate certificate)
    {
        if (certificate instanceof X509Certificate)
        {
            trustAnchors.add(new TrustAnchor((X509Certificate)certificate, null));
        }
    }

    private static KeyStore createTrustStore(String defaultType)
        throws NoSuchProviderException, KeyStoreException
    {
        String tsType = getTrustStoreType(defaultType);
        String tsProv = PropertyUtils.getStringSystemProperty("javax.net.ssl.trustStoreProvider");
        return TlsUtils.isNullOrEmpty(tsProv)
            ?   KeyStore.getInstance(tsType)
            :   KeyStore.getInstance(tsType, tsProv);
    }

    private static Set getTrustAnchors(KeyStore trustStore)
        throws KeyStoreException
    {
        if (null == trustStore)
        {
            return Collections.emptySet();
        }

        Set trustAnchors = new HashSet();
        for (Enumeration en = trustStore.aliases(); en.hasMoreElements();)
        {
            String alias = (String)en.nextElement();
            if (trustStore.isCertificateEntry(alias))
            {
                collectTrustAnchor(trustAnchors, trustStore.getCertificate(alias));
            }
            else if (trustStore.isKeyEntry(alias))
            {
                Certificate[] chain = trustStore.getCertificateChain(alias);
                if (null != chain && chain.length > 0)
                {
                    collectTrustAnchor(trustAnchors, chain[0]);
                }
            }
        }
        return trustAnchors;
    }

    private static String getTrustStoreType(String defaultType)
    {
        String tsType = PropertyUtils.getStringSystemProperty("javax.net.ssl.trustStoreType");
        return (null == tsType) ? defaultType : tsType;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy