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

eu.europa.esig.dss.crl.CRLUtilsX509CRLImpl Maven / Gradle / Ivy

package eu.europa.esig.dss.crl;

import java.io.InputStream;
import java.math.BigInteger;
import java.security.KeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.SignatureException;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;
import java.security.cert.X509CRLEntry;

import javax.security.auth.x500.X500Principal;

import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.europa.esig.dss.DSSException;
import eu.europa.esig.dss.SignatureAlgorithm;
import eu.europa.esig.dss.tsl.KeyUsageBit;
import eu.europa.esig.dss.x509.CertificateToken;

public class CRLUtilsX509CRLImpl extends AbstractCRLUtils implements ICRLUtils {

	private static final Logger LOG = LoggerFactory.getLogger(CRLUtilsX509CRLImpl.class);

	private static final BouncyCastleProvider BC_PROVIDER = new BouncyCastleProvider();

	private static final CertificateFactory CERT_FACTORY;

	static {
		try {
			Security.addProvider(BC_PROVIDER);
			CERT_FACTORY = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
		} catch (CertificateException e) {
			LOG.error(e.getMessage(), e);
			throw new DSSException("Platform does not support X509 certificate", e);
		} catch (NoSuchProviderException e) {
			LOG.error(e.getMessage(), e);
			throw new DSSException("Platform does not support BouncyCastle", e);
		}
	}

	/**
	 * This method verifies: the signature of the CRL, the key usage of its signing certificate and the coherence
	 * between the subject names of the CRL signing
	 * certificate and the issuer name of the certificate for which the verification of the revocation data is carried
	 * out. A dedicated object based on
	 * {@code CRLValidity} is created and accordingly updated.
	 *
	 * @param x509CRL
	 *            {@code X509CRL} to be verified (cannot be null)
	 * @param issuerToken
	 *            {@code CertificateToken} used to sign the {@code X509CRL} (cannot be null)
	 * @return {@code CRLValidity}
	 */
	@Override
	public CRLValidity isValidCRL(final InputStream crlStream, final CertificateToken issuerToken) {

		final X509CRLValidity crlValidity = new X509CRLValidity();

		X509CRL x509CRL = loadCRL(crlStream);

		try {
			crlValidity.setX509CRL(x509CRL);
			crlValidity.setCrlEncoded(x509CRL.getEncoded());
		} catch (CRLException e) {
			LOG.error("Unable to read the CRL binaries", e);
		}

		final String sigAlgOID = x509CRL.getSigAlgOID();
		crlValidity.setSignatureAlgorithm(SignatureAlgorithm.forOID(sigAlgOID));
		crlValidity.setThisUpdate(x509CRL.getThisUpdate());
		crlValidity.setNextUpdate(x509CRL.getNextUpdate());

		final X500Principal x509CRLIssuerX500Principal = x509CRL.getIssuerX500Principal();
		final X500Principal issuerTokenSubjectX500Principal = issuerToken.getSubjectX500Principal();
		if (x509CRLIssuerX500Principal.equals(issuerTokenSubjectX500Principal)) {
			crlValidity.setIssuerX509PrincipalMatches(true);
		}

		checkCriticalExtensions(crlValidity, x509CRL.getCriticalExtensionOIDs(), x509CRL.getExtensionValue(Extension.issuingDistributionPoint.getId()));
		extractExpiredCertsOnCRL(crlValidity, x509CRL.getExtensionValue(Extension.expiredCertsOnCRL.getId()));

		checkSignatureValue(x509CRL, issuerToken, crlValidity);
		if (crlValidity.isSignatureIntact()) {
			crlValidity.setCrlSignKeyUsage(issuerToken.checkKeyUsage(KeyUsageBit.crlSign));
		}
		return crlValidity;
	}

	private void checkSignatureValue(final X509CRL x509CRL, final CertificateToken issuerToken, final CRLValidity crlValidity) {
		try {
			x509CRL.verify(issuerToken.getPublicKey());
			crlValidity.setSignatureIntact(true);
			crlValidity.setIssuerToken(issuerToken);
		} catch (KeyException | CRLException | NoSuchAlgorithmException | SignatureException e) {
			crlValidity.setSignatureInvalidityReason(e.getClass().getSimpleName() + " - " + e.getMessage());
		} catch (NoSuchProviderException e) {
			throw new DSSException(e);
		}
	}

	@Override
	public X509CRLEntry getRevocationInfo(CRLValidity crlValidity, BigInteger serialNumber) {
		X509CRL crl = getCRL(crlValidity);
		return crl.getRevokedCertificate(serialNumber);
	}

	private X509CRL getCRL(CRLValidity crlValidity) {
		X509CRL crl = null;
		if (crlValidity instanceof X509CRLValidity) {
			X509CRLValidity x509Validity = (X509CRLValidity) crlValidity;
			crl = x509Validity.getX509CRL();
		}
		if (crl == null) {
			crl = loadCRL(crlValidity.getCrlInputStream());
		}
		return crl;
	}

	/**
	 * This method loads a CRL from the given location.
	 *
	 * @param inputStream
	 * @return
	 */
	private X509CRL loadCRL(final InputStream inputStream) {
		try {
			X509CRL crl = (X509CRL) CERT_FACTORY.generateCRL(inputStream);
			if (crl == null) {
				throw new DSSException("Unable to parse the CRL");
			}
			return crl;
		} catch (CRLException e) {
			throw new DSSException(e);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy