diff --git a/pkilint/etsi/__init__.py b/pkilint/etsi/__init__.py index cea5759..9bc6bce 100644 --- a/pkilint/etsi/__init__.py +++ b/pkilint/etsi/__init__.py @@ -292,6 +292,9 @@ def create_validators( if additional_top_level_validators: top_level_validators.extend(additional_top_level_validators) + if certificate_type in etsi_constants.EU: + extension_validators.append(en_319_412_5.QcStatementPresenceValidator()) + if ( certificate_type in etsi_constants.LEGAL_PERSON_CERTIFICATE_TYPES and certificate_type not in etsi_constants.CABF_CERTIFICATE_TYPES diff --git a/pkilint/etsi/en_319_412_5.py b/pkilint/etsi/en_319_412_5.py index 5cf4a46..9eadfca 100644 --- a/pkilint/etsi/en_319_412_5.py +++ b/pkilint/etsi/en_319_412_5.py @@ -4,7 +4,7 @@ from iso3166 import countries_by_alpha2 from iso4217 import Currency from urllib.parse import urlparse -from pyasn1_alt_modules import rfc3739 +from pyasn1_alt_modules import rfc3739, rfc5280 from pkilint.pkix import extension, Rfc2119Word import iso639 @@ -309,6 +309,24 @@ def __init__(self): ) +class QcStatementPresenceValidator(extension.ExtensionPresenceValidator): + """ + QCS-5-01: EU qualified certificates shall include QCStatements in accordance with table 2 + """ + + VALIDATION_QC_STATEMENTS_MISSING = validation.ValidationFinding( + validation.ValidationFindingSeverity.ERROR, + "etsi.en_319_412_5.qcs-5.01", + ) + + def __init__(self): + super().__init__( + extension_oid=rfc3739.id_pe_qcStatements, + validation=self.VALIDATION_QC_STATEMENTS_MISSING, + pdu_class=rfc5280.Extensions, + ) + + class QcStatementIdentifierAllowanceValidator( common.ElementIdentifierAllowanceValidator ): diff --git a/tests/integration_certificate/etsi/qncp_w_gen_legal_person_eidas_final_certificate/rsapss_bad_salt_length.crttest b/tests/integration_certificate/etsi/qncp_w_gen_legal_person_eidas_final_certificate/rsapss_bad_salt_length.crttest index 7758b09..d88a107 100644 --- a/tests/integration_certificate/etsi/qncp_w_gen_legal_person_eidas_final_certificate/rsapss_bad_salt_length.crttest +++ b/tests/integration_certificate/etsi/qncp_w_gen_legal_person_eidas_final_certificate/rsapss_bad_salt_length.crttest @@ -35,3 +35,4 @@ certificate.tbsCertificate.extensions.4.extnValue.subjectKeyIdentifier,SubjectKe certificate.tbsCertificate.extensions,NaturalPersonExtensionIdentifierAllowanceValidator,ERROR,etsi.en_319_412_2.qc_statements_extension_absent, certificate.tbsCertificate.extensions,NcpWSubjectAltNamePresenceValidator,ERROR,etsi.en_319_412_4.web-4.1.3-4.san_missing, certificate.tbsCertificate.subject.rdnSequence.3.0.value.x520CommonName,NcpWCommonNameValidator,ERROR,etsi.en_319_412_4.web-4.1.3-4.common_name_unknown_source,"Unknown source for value of common name: ""sct""" +certificate.tbsCertificate.extensions,QcStatementPresenceValidator,ERROR,etsi.en_319_412_5.qcs-5.01, diff --git a/tests/integration_certificate/etsi/qncp_w_gen_legal_person_eidas_final_certificate/rsapss_sig_alg.crttest b/tests/integration_certificate/etsi/qncp_w_gen_legal_person_eidas_final_certificate/rsapss_sig_alg.crttest index 4b7f07f..a2a2a69 100644 --- a/tests/integration_certificate/etsi/qncp_w_gen_legal_person_eidas_final_certificate/rsapss_sig_alg.crttest +++ b/tests/integration_certificate/etsi/qncp_w_gen_legal_person_eidas_final_certificate/rsapss_sig_alg.crttest @@ -34,3 +34,4 @@ certificate.tbsCertificate.extensions.4.extnValue.subjectKeyIdentifier,SubjectKe certificate.tbsCertificate.extensions,NaturalPersonExtensionIdentifierAllowanceValidator,ERROR,etsi.en_319_412_2.qc_statements_extension_absent, certificate.tbsCertificate.subject.rdnSequence.3.0.value.x520CommonName,NcpWCommonNameValidator,ERROR,etsi.en_319_412_4.web-4.1.3-4.common_name_unknown_source,"Unknown source for value of common name: ""sct""" certificate.tbsCertificate.extensions,NcpWSubjectAltNamePresenceValidator,ERROR,etsi.en_319_412_4.web-4.1.3-4.san_missing, +certificate.tbsCertificate.extensions,QcStatementPresenceValidator,ERROR,etsi.en_319_412_5.qcs-5.01,