package eu.europa.esig.dss.validation.process.bbb.xcv.sub;
import java.util.Date;
import eu.europa.esig.dss.jaxb.detailedreport.XmlRFC;
import eu.europa.esig.dss.jaxb.detailedreport.XmlSubXCV;
import eu.europa.esig.dss.validation.policy.Context;
import eu.europa.esig.dss.validation.policy.SubContext;
import eu.europa.esig.dss.validation.policy.ValidationPolicy;
import eu.europa.esig.dss.validation.process.Chain;
import eu.europa.esig.dss.validation.process.ChainItem;
import eu.europa.esig.dss.validation.process.bbb.xcv.rfc.RevocationFreshnessChecker;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.AuthorityInfoAccessPresentCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificateCryptographicCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificateExpirationCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificateIssuedToLegalPersonCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificateIssuedToNaturalPersonCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificateOnHoldCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificatePolicyIdsCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificateQCStatementIdsCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificateQualifiedCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificateRevokedCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificateSignatureValidCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CertificateSupportedByQSCDCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CommonNameCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.CountryCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.GivenNameCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.IdPkixOcspNoCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.KeyUsageCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.OrganizationNameCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.OrganizationUnitCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.PseudoUsageCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.PseudonymCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.RevocationFreshnessCheckerResult;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.RevocationInfoAccessPresentCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.SerialNumberCheck;
import eu.europa.esig.dss.validation.process.bbb.xcv.sub.checks.SurnameCheck;
import eu.europa.esig.dss.validation.reports.wrapper.CertificateWrapper;
import eu.europa.esig.jaxb.policy.CryptographicConstraint;
import eu.europa.esig.jaxb.policy.LevelConstraint;
import eu.europa.esig.jaxb.policy.MultiValuesConstraint;
public class SubX509CertificateValidation extends Chain<XmlSubXCV> {
private final CertificateWrapper currentCertificate;
private final Date currentTime;
private final Context context;
private final SubContext subContext;
private final ValidationPolicy validationPolicy;
public SubX509CertificateValidation(CertificateWrapper currentCertificate, Date currentTime, Context context, SubContext subContext,
ValidationPolicy validationPolicy) {
super(new XmlSubXCV());
result.setId(currentCertificate.getId());
result.setTrustAnchor(currentCertificate.isTrusted());
this.currentCertificate = currentCertificate;
this.currentTime = currentTime;
this.context = context;
this.subContext = subContext;
this.validationPolicy = validationPolicy;
}
@Override
protected void initChain() {
// Skip for Trusted Certificate
if (currentCertificate.isTrusted()) {
return;
}
ChainItem<XmlSubXCV> item = firstItem = serialNumber(currentCertificate, subContext);
item = item.setNextItem(surname(currentCertificate, subContext));
item = item.setNextItem(givenName(currentCertificate, subContext));
item = item.setNextItem(commonName(currentCertificate, subContext));
item = item.setNextItem(pseudonym(currentCertificate, subContext));
item = item.setNextItem(country(currentCertificate, subContext));
item = item.setNextItem(organizationUnit(currentCertificate, subContext));
item = item.setNextItem(organizationName(currentCertificate, subContext));
item = item.setNextItem(certificateSignatureValid(currentCertificate, subContext));
item = item.setNextItem(certificateCryptographic(currentCertificate, context, subContext));
item = item.setNextItem(keyUsage(currentCertificate, subContext));
item = item.setNextItem(aiaPresent(currentCertificate, subContext));
item = item.setNextItem(revocationInfoAccessPresent(currentCertificate, subContext));
item = item.setNextItem(certificateRevoked(currentCertificate, subContext));
item = item.setNextItem(certificateOnHold(currentCertificate, subContext));
item = item.setNextItem(certificateExpiration(currentCertificate, subContext));
item = item.setNextItem(certificatePolicyIds(currentCertificate, subContext));
item = item.setNextItem(certificateQCStatementIds(currentCertificate, subContext));
item = item.setNextItem(certificateQualified(currentCertificate, subContext));
item = item.setNextItem(certificateSupportedByQSCD(currentCertificate, subContext));
item = item.setNextItem(pseudoUsage(currentCertificate, subContext));
item = item.setNextItem(certificateIssuedToLegalPerson(currentCertificate, subContext));
item = item.setNextItem(certificateIssuedToNaturalPerson(currentCertificate, subContext));
if (!isRevocationNoNeedCheck(currentCertificate)) {
RevocationFreshnessChecker rfc = new RevocationFreshnessChecker(currentCertificate.getLatestRevocationData(), currentTime, context, subContext,
validationPolicy);
XmlRFC rfcResult = rfc.execute();
result.setRFC(rfcResult);
item = item.setNextItem(checkRevocationFreshnessCheckerResult(rfcResult));
} else {
item = item.setNextItem(idPkixOcspNoCheck());
}
}
/*
* A signing certificate includes the id-pkix-ocsp-nocheck extension. This extension informs the OCSP client that
* the OCSP signing certificate should not be checked for revocation during the lifetime of the certificate. The
* OCSP Signing certificate should therefore have a short lifetime.
*/
private boolean isRevocationNoNeedCheck(CertificateWrapper certificate) {
if (certificate.isIdPkixOcspNoCheck()) {
return currentTime.compareTo(certificate.getNotBefore()) >= 0 && currentTime.compareTo(certificate.getNotAfter()) <= 0;
}
return false;
}
private ChainItem<XmlSubXCV> certificateExpiration(CertificateWrapper certificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateNotExpiredConstraint(context, subContext);
return new CertificateExpirationCheck(result, certificate, currentTime, constraint);
}
private ChainItem<XmlSubXCV> keyUsage(CertificateWrapper certificate, SubContext subContext) {
MultiValuesConstraint constraint = validationPolicy.getCertificateKeyUsageConstraint(context, subContext);
return new KeyUsageCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> aiaPresent(CertificateWrapper certificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateAuthorityInfoAccessPresentConstraint(context, subContext);
return new AuthorityInfoAccessPresentCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> revocationInfoAccessPresent(CertificateWrapper certificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateRevocationInfoAccessPresentConstraint(context, subContext);
return new RevocationInfoAccessPresentCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> surname(CertificateWrapper certificate, SubContext subContext) {
MultiValuesConstraint constraint = validationPolicy.getCertificateSurnameConstraint(context, subContext);
return new SurnameCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> givenName(CertificateWrapper certificate, SubContext subContext) {
MultiValuesConstraint constraint = validationPolicy.getCertificateGivenNameConstraint(context, subContext);
return new GivenNameCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> commonName(CertificateWrapper certificate, SubContext subContext) {
MultiValuesConstraint constraint = validationPolicy.getCertificateCommonNameConstraint(context, subContext);
return new CommonNameCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> pseudonym(CertificateWrapper certificate, SubContext subContext) {
MultiValuesConstraint constraint = validationPolicy.getCertificatePseudonymConstraint(context, subContext);
return new PseudonymCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> country(CertificateWrapper certificate, SubContext subContext) {
MultiValuesConstraint constraint = validationPolicy.getCertificateCountryConstraint(context, subContext);
return new CountryCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> organizationName(CertificateWrapper certificate, SubContext subContext) {
MultiValuesConstraint constraint = validationPolicy.getCertificateOrganizationNameConstraint(context, subContext);
return new OrganizationNameCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> organizationUnit(CertificateWrapper certificate, SubContext subContext) {
MultiValuesConstraint constraint = validationPolicy.getCertificateOrganizationUnitConstraint(context, subContext);
return new OrganizationUnitCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> serialNumber(CertificateWrapper signingCertificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateSerialNumberConstraint(context, subContext);
return new SerialNumberCheck(result, signingCertificate, constraint);
}
private ChainItem<XmlSubXCV> pseudoUsage(CertificateWrapper signingCertificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificatePseudoUsageConstraint(context, subContext);
return new PseudoUsageCheck(result, signingCertificate, constraint);
}
private ChainItem<XmlSubXCV> certificateSignatureValid(CertificateWrapper certificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateSignatureConstraint(context, subContext);
return new CertificateSignatureValidCheck<XmlSubXCV>(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> certificateRevoked(CertificateWrapper certificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateNotRevokedConstraint(context, subContext);
return new CertificateRevokedCheck(result, certificate, constraint, subContext);
}
private ChainItem<XmlSubXCV> certificateOnHold(CertificateWrapper certificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateNotOnHoldConstraint(context, subContext);
return new CertificateOnHoldCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> certificatePolicyIds(CertificateWrapper certificate, SubContext subContext) {
MultiValuesConstraint constraint = validationPolicy.getCertificatePolicyIdsConstraint(context, subContext);
return new CertificatePolicyIdsCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> certificateQCStatementIds(CertificateWrapper certificate, SubContext subContext) {
MultiValuesConstraint constraint = validationPolicy.getCertificateQCStatementIdsConstraint(context, subContext);
return new CertificateQCStatementIdsCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> certificateCryptographic(CertificateWrapper certificate, Context context, SubContext subcontext) {
CryptographicConstraint cryptographicConstraint = validationPolicy.getCertificateCryptographicConstraint(context, subcontext);
return new CertificateCryptographicCheck(result, certificate, currentTime, cryptographicConstraint);
}
private ChainItem<XmlSubXCV> certificateQualified(CertificateWrapper certificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateQualificationConstraint(context, subContext);
return new CertificateQualifiedCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> certificateSupportedByQSCD(CertificateWrapper certificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateSupportedByQSCDConstraint(context, subContext);
return new CertificateSupportedByQSCDCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> certificateIssuedToLegalPerson(CertificateWrapper certificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateIssuedToLegalPersonConstraint(context, subContext);
return new CertificateIssuedToLegalPersonCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> certificateIssuedToNaturalPerson(CertificateWrapper certificate, SubContext subContext) {
LevelConstraint constraint = validationPolicy.getCertificateIssuedToNaturalPersonConstraint(context, subContext);
return new CertificateIssuedToNaturalPersonCheck(result, certificate, constraint);
}
private ChainItem<XmlSubXCV> checkRevocationFreshnessCheckerResult(XmlRFC rfcResult) {
return new RevocationFreshnessCheckerResult(result, rfcResult, getFailLevelConstraint());
}
private ChainItem<XmlSubXCV> idPkixOcspNoCheck() {
return new IdPkixOcspNoCheck(result, getFailLevelConstraint());
}
}