package eu.europa.esig.dss.validation.process.qmatrix.qualification; import java.util.Date; import java.util.List; import java.util.Set; import eu.europa.esig.dss.jaxb.detailedreport.XmlConclusion; import eu.europa.esig.dss.jaxb.detailedreport.XmlSignatureAnalysis; import eu.europa.esig.dss.jaxb.detailedreport.XmlTLAnalysis; import eu.europa.esig.dss.utils.Utils; import eu.europa.esig.dss.validation.SignatureQualification; import eu.europa.esig.dss.validation.policy.ValidationPolicy; import eu.europa.esig.dss.validation.policy.rules.Indication; import eu.europa.esig.dss.validation.process.Chain; import eu.europa.esig.dss.validation.process.ChainItem; import eu.europa.esig.dss.validation.process.Condition; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.AcceptableTrustedListCheck; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.AdESAcceptableCheck; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.CertificateAndServiceConsistencyCheck; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.CertificatePathTrustedCheck; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.ForeSignatureAtSigningTimeCheck; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.QSCDCertificateAtSigningTimeCheck; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.QualifiedCertificateAtCertificateIssuanceCheck; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.QualifiedCertificateAtSigningTimeCheck; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.ServiceConsistencyCheck; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.filter.TrustedServiceFilter; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.filter.TrustedServicesFilterFactory; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.qualified.QualifiedStatus; import eu.europa.esig.dss.validation.process.qmatrix.qualification.checks.type.Type; import eu.europa.esig.dss.validation.reports.wrapper.CertificateWrapper; import eu.europa.esig.dss.validation.reports.wrapper.DiagnosticData; import eu.europa.esig.dss.validation.reports.wrapper.SignatureWrapper; import eu.europa.esig.dss.validation.reports.wrapper.TrustedServiceWrapper; public class SignatureQualificationBlock extends Chain<XmlSignatureAnalysis> { private final XmlConclusion etsi319102Conclusion; private final List<XmlTLAnalysis> tlAnalysis; private final SignatureWrapper signature; private final DiagnosticData diagnosticData; private final ValidationPolicy policy; private QualifiedCertificateAtSigningTimeCheck qualifiedAtSigningTime; private ForeSignatureAtSigningTimeCheck foreSignatureAtSigningTime; private QSCDCertificateAtSigningTimeCheck qscdAtSigningTime; public SignatureQualificationBlock(XmlConclusion etsi319102Conclusion, List<XmlTLAnalysis> tlAnalysis, SignatureWrapper signature, DiagnosticData diagnosticData, ValidationPolicy policy) { super(new XmlSignatureAnalysis()); result.setId(signature.getId()); this.etsi319102Conclusion = etsi319102Conclusion; this.tlAnalysis = tlAnalysis; this.signature = signature; this.diagnosticData = diagnosticData; this.policy = policy; } @Override protected void initChain() { String signingCertificateId = signature.getSigningCertificateId(); CertificateWrapper signingCertificate = diagnosticData.getUsedCertificateById(signingCertificateId); ChainItem<XmlSignatureAnalysis> item = firstItem = isAdES(etsi319102Conclusion); item = item.setNextItem(certificatePathTrusted(signingCertificate)); if (signingCertificate != null && signingCertificate.hasTrustedServices()) { XmlTLAnalysis lotlAnalysis = getTLAnalysis(diagnosticData.getLOTLCountryCode()); if (lotlAnalysis != null) { item = item.setNextItem(isAcceptableTL(lotlAnalysis)); } Set<String> trustedListCountryCodes = signingCertificate.getTrustedListCountryCodes(); for (String countryCode : trustedListCountryCodes) { XmlTLAnalysis currentTL = getTLAnalysis(countryCode); if (currentTL != null) { item = item.setNextItem(isAcceptableTL(currentTL)); } } List<TrustedServiceWrapper> originalTSPs = signingCertificate.getTrustedServices(); // 1. filter by service for CAQC TrustedServiceFilter filter = TrustedServicesFilterFactory.createFilterForAcceptableCAQC(); List<TrustedServiceWrapper> caqcServices = filter.filter(originalTSPs); // 2. Consistency of trust services ? item = item.setNextItem(servicesConsistency(caqcServices)); item = item.setNextItem(serviceAndCertificateConsistency(caqcServices, signingCertificate)); Date bestSigningTime = signature.getDateTime(); // TODO // Article 32 : // (a) the certificate that supports the signature was, at the time of signing, a qualified certificate for // electronic signature complying with Annex I; qualifiedAtSigningTime = (QualifiedCertificateAtSigningTimeCheck) qualifiedCertificateAtSigningTime(signingCertificate, bestSigningTime, caqcServices); item = item.setNextItem(qualifiedAtSigningTime); foreSignatureAtSigningTime = (ForeSignatureAtSigningTimeCheck) foreSignatureAtSigningTime(signingCertificate, bestSigningTime, caqcServices); item = item.setNextItem(foreSignatureAtSigningTime); // (b) the qualified certificate // 1. was issued by a qualified trust service provider item = item.setNextItem(qualifiedCertificateAtIssuance(signingCertificate, caqcServices)); // 2. was valid at the time of signing; // covered in isAdES // (c) the signature validation data corresponds to the data provided to the relying party; // covered in isAdES // (d) the unique set of data representing the signatory in the certificate is correctly provided to the // relying party; // covered in isAdES // (e) the use of any pseudonym is clearly indicated to the relying party if a pseudonym was used at the // time of signing; // covered in isAdES // (f) the electronic signature was created by a qualified electronic signature creation device; qscdAtSigningTime = (QSCDCertificateAtSigningTimeCheck) qscdAtSigningTime(signingCertificate, bestSigningTime, caqcServices, qualifiedAtSigningTime); item = item.setNextItem(qscdAtSigningTime); // (g) the integrity of the signed data has not been compromised; // covered in isAdES } } private XmlTLAnalysis getTLAnalysis(String countryCode) { for (XmlTLAnalysis xmlTLAnalysis : tlAnalysis) { if (Utils.areStringsEqual(countryCode, xmlTLAnalysis.getCountryCode())) { return xmlTLAnalysis; } } return null; } @Override protected void addAdditionalInfo() { collectErrorsWarnsInfos(); setIndication(); determineFinalQualification(); } private void determineFinalQualification() { SignatureQualification sigQualif = SignatureQualification.NA; if (isAcceptableConclusion() && qualifiedAtSigningTime != null && foreSignatureAtSigningTime != null && qscdAtSigningTime != null) { QualifiedStatus qualifiedStatus = qualifiedAtSigningTime.getQualifiedStatus(); boolean qc = QualifiedStatus.isQC(qualifiedStatus); Type type = foreSignatureAtSigningTime.getType(); boolean qscd = qscdAtSigningTime.check(); sigQualif = QualificationMatrix.getSignatureQualification(etsi319102Conclusion.getIndication(), qc, type, qscd); } result.setSignatureQualification(sigQualif); } private boolean isAcceptableConclusion() { XmlConclusion conclusion = result.getConclusion(); return conclusion != null && Indication.FAILED != conclusion.getIndication(); } private void setIndication() { XmlConclusion conclusion = result.getConclusion(); if (conclusion != null) { if (Utils.isCollectionNotEmpty(conclusion.getErrors())) { conclusion.setIndication(Indication.FAILED); } else if (Utils.isCollectionNotEmpty(conclusion.getWarnings())) { conclusion.setIndication(Indication.INDETERMINATE); } else { conclusion.setIndication(Indication.PASSED); } } } private ChainItem<XmlSignatureAnalysis> certificatePathTrusted(CertificateWrapper signingCertificate) { return new CertificatePathTrustedCheck(result, signingCertificate, getFailLevelConstraint()); } private ChainItem<XmlSignatureAnalysis> isAcceptableTL(XmlTLAnalysis xmlTLAnalysis) { return new AcceptableTrustedListCheck(result, xmlTLAnalysis, getFailLevelConstraint()); } private ChainItem<XmlSignatureAnalysis> servicesConsistency(List<TrustedServiceWrapper> caqcServices) { return new ServiceConsistencyCheck(result, caqcServices, policy.getTLConsistencyConstraint()); } private ChainItem<XmlSignatureAnalysis> serviceAndCertificateConsistency(List<TrustedServiceWrapper> caqcServices, CertificateWrapper signingCertificate) { return new CertificateAndServiceConsistencyCheck(result, signingCertificate, caqcServices, getWarnLevelConstraint()); } private ChainItem<XmlSignatureAnalysis> isAdES(XmlConclusion etsi319102Conclusion) { return new AdESAcceptableCheck(result, etsi319102Conclusion, getWarnLevelConstraint()); } private ChainItem<XmlSignatureAnalysis> qualifiedCertificateAtSigningTime(CertificateWrapper signingCertificate, Date signingTime, List<TrustedServiceWrapper> caqcServices) { return new QualifiedCertificateAtSigningTimeCheck(result, signingCertificate, signingTime, caqcServices, getWarnLevelConstraint()); } private ChainItem<XmlSignatureAnalysis> foreSignatureAtSigningTime(CertificateWrapper signingCertificate, Date signingTime, List<TrustedServiceWrapper> caqcServices) { return new ForeSignatureAtSigningTimeCheck(result, signingCertificate, signingTime, caqcServices, getWarnLevelConstraint()); } private ChainItem<XmlSignatureAnalysis> qualifiedCertificateAtIssuance(CertificateWrapper signingCertificate, List<TrustedServiceWrapper> caqcServices) { return new QualifiedCertificateAtCertificateIssuanceCheck(result, signingCertificate, caqcServices, getWarnLevelConstraint()); } private ChainItem<XmlSignatureAnalysis> qscdAtSigningTime(CertificateWrapper signingCertificate, Date signingTime, List<TrustedServiceWrapper> caqcServices, Condition qualifiedStatusAtSigningTime) { return new QSCDCertificateAtSigningTimeCheck(result, signingCertificate, signingTime, caqcServices, qualifiedStatusAtSigningTime, getWarnLevelConstraint()); } }