package org.bouncycastle.est.jcajce; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.UnrecoverableKeyException; import java.security.cert.CRL; import java.security.cert.CertPathBuilder; import java.security.cert.CertStore; import java.security.cert.CertificateException; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.PKIXBuilderParameters; import java.security.cert.PKIXCertPathValidatorResult; import java.security.cert.TrustAnchor; import java.security.cert.X509CertSelector; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Iterator; import java.util.Set; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.X509TrustManager; import org.bouncycastle.asn1.x509.ExtendedKeyUsage; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.cert.X509CertificateHolder; /** * General utility methods for building common objects for supporting the JCA/JCE/JSSE. */ public class JcaJceUtils { public static X509TrustManager getTrustAllTrustManager() { // // Trust manager signal distrust by throwing exceptions. // This one trust all by doing nothing. // return new X509TrustManager() { public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; } }; } public static X509TrustManager[] getCertPathTrustManager(final Set<TrustAnchor> anchors, final CRL[] revocationLists) { final X509Certificate[] x509CertificateTrustAnchors = new X509Certificate[anchors.size()]; int c = 0; for (Iterator it = anchors.iterator(); it.hasNext();) { TrustAnchor ta = (TrustAnchor)it.next(); x509CertificateTrustAnchors[c++] = ta.getTrustedCert(); } return new X509TrustManager[]{new X509TrustManager() { public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { } public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { try { CertStore certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(Arrays.asList(x509Certificates)), "BC"); CertPathBuilder pathBuilder = CertPathBuilder.getInstance("PKIX", "BC"); X509CertSelector constraints = new X509CertSelector(); constraints.setCertificate(x509Certificates[0]); PKIXBuilderParameters param = new PKIXBuilderParameters(anchors, constraints); param.addCertStore(certStore); if (revocationLists != null) { param.setRevocationEnabled(true); param.addCertStore( CertStore.getInstance( "Collection", new CollectionCertStoreParameters(Arrays.asList(revocationLists) ))); } else { param.setRevocationEnabled(false); } PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult)pathBuilder.build(param); validateServerCertUsage(x509Certificates[0]); } catch (CertificateException e) { throw e; } catch (GeneralSecurityException e) { throw new CertificateException("unable to process certificates: " + e.getMessage(), e); } } public X509Certificate[] getAcceptedIssuers() { X509Certificate[] rv = new X509Certificate[x509CertificateTrustAnchors.length]; System.arraycopy(x509CertificateTrustAnchors, 0, rv, 0, rv.length); return rv; } } }; } public static void validateServerCertUsage(X509Certificate x509Certificate) throws CertificateException { try { X509CertificateHolder cert = new X509CertificateHolder(x509Certificate.getEncoded()); KeyUsage keyUsage = KeyUsage.fromExtensions(cert.getExtensions()); if (keyUsage != null) { if (keyUsage.hasUsages(KeyUsage.keyCertSign)) { throw new CertificateException("Key usage must not contain keyCertSign"); } if (!(keyUsage.hasUsages(KeyUsage.digitalSignature) || keyUsage.hasUsages(KeyUsage.keyEncipherment))) { throw new CertificateException("Key usage must be none, digitalSignature or keyEncipherment"); } } // // Check extended key usage. // ExtendedKeyUsage extendedKeyUsage = ExtendedKeyUsage.fromExtensions(cert.getExtensions()); if (extendedKeyUsage != null) { if (!(extendedKeyUsage.hasKeyPurposeId(KeyPurposeId.id_kp_serverAuth) || extendedKeyUsage.hasKeyPurposeId(KeyPurposeId.id_kp_msSGC) || extendedKeyUsage.hasKeyPurposeId(KeyPurposeId.id_kp_nsSGC))) { throw new CertificateException("Certificate extended key usage must include serverAuth, msSGC or nsSGC"); } } } catch (CertificateException c) { throw c; } catch (Exception e) { throw new CertificateException(e.getMessage(), e); } } public static KeyManagerFactory createKeyManagerFactory( String type, String provider, KeyStore clientKeyStore, char[] clientKeyStorePass) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, NoSuchProviderException { KeyManagerFactory keyManagerFactory = null; if (type == null && provider == null) { keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); } else if (provider == null) { keyManagerFactory = KeyManagerFactory.getInstance(type); } else { keyManagerFactory = KeyManagerFactory.getInstance(type, provider); } keyManagerFactory.init(clientKeyStore, clientKeyStorePass); return keyManagerFactory; } }