From d2287322a6be4ede4fd14e87204bc5a22e0a369d Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Fri, 15 Dec 2023 10:45:39 -0500 Subject: [PATCH 1/6] Bump version, fix the reported validation for negative validity periods --- VERSION.txt | 2 +- pkilint/cabf/smime/__init__.py | 2 - pkilint/pkix/time.py | 4 +- .../pkix/negative_validity_period.crttest | 37 +++++++++++++++++++ 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 tests/integration_certificate/pkix/negative_validity_period.crttest diff --git a/VERSION.txt b/VERSION.txt index b5d0ec5..6f060dc 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -0.9.8 \ No newline at end of file +0.9.9 \ No newline at end of file diff --git a/pkilint/cabf/smime/__init__.py b/pkilint/cabf/smime/__init__.py index ee25e09..1cb1fbf 100644 --- a/pkilint/cabf/smime/__init__.py +++ b/pkilint/cabf/smime/__init__.py @@ -1,10 +1,8 @@ import operator from typing import Mapping, Tuple -from cryptography import x509 from dateutil.relativedelta import relativedelta from pyasn1.type import univ -from pyasn1.type.univ import ObjectIdentifier from pyasn1_alt_modules import rfc8398, rfc5280, rfc4262 import pkilint.adobe.asn1 as adobe_asn1 diff --git a/pkilint/pkix/time.py b/pkilint/pkix/time.py index e1647f4..e145cbe 100644 --- a/pkilint/pkix/time.py +++ b/pkilint/pkix/time.py @@ -158,6 +158,8 @@ def validate_date_range(self, start_datetime, end_datetime): class SaneValidityPeriodValidator(ValidityPeriodDifferenceValidator): def __init__(self, *, end_validity_node_retriever, validation, **kwargs): + self._invalid_validity_period_validation = validation + super().__init__( end_validity_node_retriever=end_validity_node_retriever, validations=[validation], @@ -167,7 +169,7 @@ def __init__(self, *, end_validity_node_retriever, validation, **kwargs): def validate_date_range(self, start_datetime, end_datetime): if start_datetime > end_datetime: raise validation.ValidationFindingEncountered( - self._validations[0], + self._invalid_validity_period_validation, f'Start of validity period "{start_datetime}" is greater than ' f'end of validity period "{end_datetime}"' ) diff --git a/tests/integration_certificate/pkix/negative_validity_period.crttest b/tests/integration_certificate/pkix/negative_validity_period.crttest new file mode 100644 index 0000000..5aa3a68 --- /dev/null +++ b/tests/integration_certificate/pkix/negative_validity_period.crttest @@ -0,0 +1,37 @@ +-----BEGIN CERTIFICATE----- +MIIFwjCCA6qgAwIBAgIUH/nOhctN2lspZ2LasyeIMEixJzEwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCVVMxHzAdBgNVBAoMFkZvbyBJbmR1c3RyaWVzIExpbWl0 +ZWQxGDAWBgNVBAMMD0ludGVybWVkaWF0ZSBDQTAeFw0yMzA0MTkwMDAwMDBaFw0y +MzAxMTgyMzU5NTlaME4xIjAgBgNVBAMMGWhhbmFrby55YW1hZGFAZXhhbXBsZS5j +b20xKDAmBgkqhkiG9w0BCQEWGWhhbmFrby55YW1hZGFAZXhhbXBsZS5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCw+egZQ6eumJKq3hfKfED4dE/t +L4FI5sjqont9ABVI+1GSqyi1bFBgsRjM0THllIdMbKmJtWwnKW8J+5OgNN8y6Xxv +8JmM/Y5vQt2lis0fqXmG8UTz0VTWdlAXXmhUs6lSADvAaIe4RVrCsZ97L3ZQTryY +7JRVcbB4khUN3Gp0yg+801SXzoFTTa+UGIRLE66jH51aa5VXu99hnv1OiH8tQrjd +i8mH6uG/icq4XuIeNWMF32wHqIOOPvQcWV3M5D2vxJEj702Ku6k9OQXkAo17qRSE +onWW4HtLbtmS8He1JNPc/n3dVUm+fM6NoDXPoLP7j55G9zKyqGtGAWXAj1MTAgMB +AAGjggGcMIIBmDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAfBgNVHSME +GDAWgBTWRAAyfKgN/6xPa2buta6bLMU4VDAdBgNVHQ4EFgQUiRlZXg7xafXLvUfh +NPzimMxpMJEwFAYDVR0gBA0wCzAJBgdngQwBBQECMD0GA1UdHwQ2MDQwMqAwoC6G +LGh0dHA6Ly9jcmwuY2EuZXhhbXBsZS5jb20vaXNzdWluZ19jYV9jcmwuY3JsMEsG +CCsGAQUFBwEBBD8wPTA7BggrBgEFBQcwAoYvaHR0cDovL3JlcG9zaXRvcnkuY2Eu +ZXhhbXBsZS5jb20vaXNzdWluZ19jYS5kZXIwHQYDVR0lBBYwFAYIKwYBBQUHAwQG +CCsGAQUFBwMCMHcGA1UdEQRwMG6BGWhhbmFrby55YW1hZGFAZXhhbXBsZS5jb22g +KQYKKwYBBAGCNxQCA6AbDBloYW5ha28ueWFtYWRhQGV4YW1wbGUuY29toCYGCCsG +AQUFBwgJoBoMGOWxseeUsOiKseWtkEBleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsF +AAOCAgEAg4rIcKGMfLh347FX/Y12lx7b9/iVrjsX7lsliirpITuPmfCli76JVrO0 +Fqypfdd2P4ZVvH9WTpQUhRBv06kwHkJRkgpqNPO0WOpNVnsK8vcP1/RylDiJGryz +u6AzOSDqsxomFD6hm71XRYcsgBXXNPUzSGhbqUeuBuZwZe1WmP/yuvNpghMvlWFc +jAHktC9FuNpHhQ/3zZ20GUc6AQwwtn8rviFSwQihVJDJkGiGaJUc7lVVoswx87bS +oGpVluEIY/RK2HsXU0kmek4qq2t9v1OgRL98ZqUgOS26ooOXxqnR3QMx1S5KSLy9 ++hK6y2gPhyiHoaPVTk4s54Es/YDtbCz7piyyyp3DEIzmgrwB/mG2IbOv6dT8Za5B +R7A+ggB7uwo3zYxKd2SFIDmXb+n9ML/s6/3aeyKJms4FmRq+fX8icb+lvVeLMhlC +Re5MFL2tkb72BFku0eeUde4iUnw93fzG6+Wl8VPCzYOwV0j+UTiyygcXaEZW+TpT +EmyY/fQ/7TCbGp+8Ur3rLlY5Okt5T83MmZdMFIHLQxaZUXkT2dBaSnh3VfNKFi0a +re9xdiBQZGkMkvWiKTjrUOwLXSNBnP6TXO9zn51tTK4KPZnQvNvULtn4H7z3FhfW +kie/jPNYkFvMzOaawwPAhG9R6G2ZB7cTOuG0Uu863Hkh5XX2oAo= +-----END CERTIFICATE----- + +node_path,validator,severity,code,message +certificate.tbsCertificate.validity.notBefore,CertificateSaneValidityPeriodValidator,ERROR,pkix.certificate_negative_validity_period,"Start of validity period ""2023-04-19 00:00:00+00:00"" is greater than end of validity period ""2023-01-18 23:59:59+00:00""" +certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix.subject_key_identifier_method_1_identified From 9639b42e8006dea5f8d2245724a88ffff6186504 Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Fri, 15 Dec 2023 10:52:07 -0500 Subject: [PATCH 2/6] Fix QCStatement decoder map for QCCompliance and QcSSCD statements --- pkilint/etsi/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkilint/etsi/__init__.py b/pkilint/etsi/__init__.py index fe77bd9..89ff314 100644 --- a/pkilint/etsi/__init__.py +++ b/pkilint/etsi/__init__.py @@ -1,11 +1,12 @@ from pkilint.etsi.asn1 import en_319_412_5, ts_119_495 +from pkilint import document ETSI_QC_STATEMENTS_MAPPINGS = { - en_319_412_5.id_etsi_qcs_QcCompliance: None, + en_319_412_5.id_etsi_qcs_QcCompliance: document.ValueDecoder.VALUE_NODE_ABSENT, en_319_412_5.id_etsi_qcs_QcLimitValue: en_319_412_5.QcEuLimitValue(), en_319_412_5.id_etsi_qcs_QcRetentionPeriod: en_319_412_5.QcEuRetentionPeriod(), - en_319_412_5.id_etsi_qcs_QcSSCD: None, + en_319_412_5.id_etsi_qcs_QcSSCD: document.ValueDecoder.VALUE_NODE_ABSENT, en_319_412_5.id_etsi_qcs_QcPDS: en_319_412_5.QcEuPDS(), en_319_412_5.id_etsi_qcs_QcType: en_319_412_5.QcType(), en_319_412_5.id_etsi_qcs_QcCClegislation: en_319_412_5.QcCClegislation(), From e3af04b536eb459dc1d548b92ac90473caa7c169 Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Fri, 15 Dec 2023 16:13:42 -0500 Subject: [PATCH 3/6] Add RFC7093 SKID calculation support --- pkilint/pkix/certificate/certificate_key.py | 64 +++++++++++++++---- pkilint/util.py | 6 +- .../pkix/rfc7093_method_1.crttest | 20 ++++++ .../pkix/rfc7093_method_2.crttest | 36 +++++++++++ .../pkix/rfc7093_method_3.crttest | 36 +++++++++++ .../pkix/unknown_skid_method.crttest | 36 +++++++++++ 6 files changed, 181 insertions(+), 17 deletions(-) create mode 100644 tests/integration_certificate/pkix/rfc7093_method_1.crttest create mode 100644 tests/integration_certificate/pkix/rfc7093_method_2.crttest create mode 100644 tests/integration_certificate/pkix/rfc7093_method_3.crttest create mode 100644 tests/integration_certificate/pkix/unknown_skid_method.crttest diff --git a/pkilint/pkix/certificate/certificate_key.py b/pkilint/pkix/certificate/certificate_key.py index 7d0dda4..94ac70a 100644 --- a/pkilint/pkix/certificate/certificate_key.py +++ b/pkilint/pkix/certificate/certificate_key.py @@ -1,6 +1,7 @@ import binascii from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding, rsa, ec from pyasn1.codec.der.encoder import encode from pyasn1.type import univ @@ -102,57 +103,92 @@ def __init__(self, *, decode_func, **kwargs): ) -def _calculate_method2_hash(sha1_hash): - last_8_octets = bytearray(sha1_hash[12:]) - last_8_octets[0] = 0x40 | (last_8_octets[0] & 0xF) - - return bytes(last_8_octets) - - class SubjectKeyIdentifierValidator(validation.Validator): VALIDATION_UNKNOWN_METHOD = validation.ValidationFinding( validation.ValidationFindingSeverity.NOTICE, 'pkix.unknown_subject_key_identifier_calculation_method' ) + # TODO: consider renaming the finding code after weighing risk of user breakage VALIDATION_METHOD_1 = validation.ValidationFinding( validation.ValidationFindingSeverity.INFO, 'pkix.subject_key_identifier_method_1_identified' ) + # TODO: consider renaming the finding code after weighing risk of user breakage VALIDATION_METHOD_2 = validation.ValidationFinding( validation.ValidationFindingSeverity.INFO, 'pkix.subject_key_identifier_method_2_identified' ) + VALIDATION_RFC7093_METHOD_1 = validation.ValidationFinding( + validation.ValidationFindingSeverity.INFO, + 'pkix_subject_key_identifier_rfc7093_method_1_identified' + ) + + VALIDATION_RFC7093_METHOD_2 = validation.ValidationFinding( + validation.ValidationFindingSeverity.INFO, + 'pkix_subject_key_identifier_rfc7093_method_2_identified' + ) + + VALIDATION_RFC7093_METHOD_3 = validation.ValidationFinding( + validation.ValidationFindingSeverity.INFO, + 'pkix_subject_key_identifier_rfc7093_method_3_identified' + ) + def __init__(self): super().__init__( validations=[ self.VALIDATION_UNKNOWN_METHOD, self.VALIDATION_METHOD_1, self.VALIDATION_METHOD_2, + self.VALIDATION_RFC7093_METHOD_1, + self.VALIDATION_RFC7093_METHOD_2, + self.VALIDATION_RFC7093_METHOD_3, ], pdu_class=rfc5280.SubjectKeyIdentifier ) + @staticmethod + def _calculate_rfc5280_method2_id(sha1_hash): + last_8_octets = bytearray(sha1_hash[12:]) + last_8_octets[0] = 0x40 | (last_8_octets[0] & 0xF) + + return bytes(last_8_octets) + + _RFC7093_HASH_CLS_TO_FINDINGS = { + hashes.SHA256: VALIDATION_RFC7093_METHOD_1, + hashes.SHA384: VALIDATION_RFC7093_METHOD_2, + hashes.SHA512: VALIDATION_RFC7093_METHOD_3, + } + + # TODO: support RFC 7093 method 4 + @staticmethod + def _calculate_rfc7093_method_hash(public_key_octets, hash_cls): + h = util.calculate_hash(public_key_octets, hash_cls()) + + # leftmost 160 bits (i.e., 20 octets) + return h[:20] + def validate(self, node): public_key_node = node.document.root.navigate( 'tbsCertificate.subjectPublicKeyInfo.subjectPublicKey' ) - public_key_bytes = public_key_node.pdu.asOctets() - public_key_sha1 = util.calculate_sha1_hash(public_key_bytes) - - method2_hash = _calculate_method2_hash(public_key_sha1) + public_key_octets = public_key_node.pdu.asOctets() identifier_octets = bytes(node.pdu) - if public_key_sha1 == identifier_octets: + public_key_sha1 = util.calculate_sha1_hash(public_key_octets) + + if identifier_octets == public_key_sha1: finding = self.VALIDATION_METHOD_1 - elif method2_hash == identifier_octets: + elif identifier_octets == SubjectKeyIdentifierValidator._calculate_rfc5280_method2_id(public_key_sha1): finding = self.VALIDATION_METHOD_2 else: - finding = self.VALIDATION_UNKNOWN_METHOD + finding = next((f for h, f in SubjectKeyIdentifierValidator._RFC7093_HASH_CLS_TO_FINDINGS.items() if + SubjectKeyIdentifierValidator._calculate_rfc7093_method_hash( + public_key_octets, h) == identifier_octets), self.VALIDATION_UNKNOWN_METHOD) raise validation.ValidationFindingEncountered(finding) diff --git a/pkilint/util.py b/pkilint/util.py index 51fc72c..1a4d0a6 100644 --- a/pkilint/util.py +++ b/pkilint/util.py @@ -7,15 +7,15 @@ from pkilint.report import report_wrapper, REPORT_FORMATS -def _calculate_hash(octets, hash_algo): +def calculate_hash(octets: bytes, hash_algo: hashes.HashAlgorithm) -> bytes: h = hashes.Hash(hash_algo) h.update(octets) return h.finalize() -def calculate_sha1_hash(octets): - return _calculate_hash(octets, hashes.SHA1()) +def calculate_sha1_hash(octets: bytes) -> bytes: + return calculate_hash(octets, hashes.SHA1()) def argparse_enum_type_parser(enum_type): diff --git a/tests/integration_certificate/pkix/rfc7093_method_1.crttest b/tests/integration_certificate/pkix/rfc7093_method_1.crttest new file mode 100644 index 0000000..45f91f6 --- /dev/null +++ b/tests/integration_certificate/pkix/rfc7093_method_1.crttest @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIICyjCCAlCgAwIBAgIQY1zINBzZ6YS8yyP57Ql/HjAKBggqhkjOPQQDAzBWMQsw +CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg +R3JvdXAxHDAaBgNVBAMTEyhGQUtFKSBJU1JHIFJvb3QgWDIwHhcNMjMwOTI1MDAw +MDAwWhcNMjYwOTI0MjM1OTU5WjBAMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUKEZB +S0UpIExldCdzIEVuY3J5cHQxEjAQBgNVBAMTCShGQUtFKSBFNzB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABOn6Rxf8w7JMveol0MqmodXTPkxfQDCCuZIWo7NsL9nFSVrp +FNOajWXg1uxujC25VK62gNRP5OSoiAAnlZ6CUI6/cWWHF78QWyLk3SS6mrPrlBUl +TZr3DrFi67X4+R93GaOB+DCB9TAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYI +KwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE +FLmhijFtd+cJnmo9dqY7HHRulw77MB8GA1UdIwQYMBaAFDnxnbEOFolx9/jcKlXc +CcyDWni7MDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gyLmku +bGVuY3Iub3JnLzATBgNVHSAEDDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAY +hhZodHRwOi8veDIuYy5sZW5jci5vcmcvMAoGCCqGSM49BAMDA2gAMGUCMAO7SkY9 +m1jgu8HC/+WQEPKzhU1Eze+AZF3yCjbxc08xIThaxIL3m3syDXAMyfbtfQIxAMLy +AZvTbDmzq9nfzN4wz4KGkMuy0Ab7nuguoYht4LNEZG/M+uz3eh6rCEzoxIoy8w== +-----END CERTIFICATE----- + +node_path,validator,severity,code,message +certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix_subject_key_identifier_rfc7093_method_1_identified diff --git a/tests/integration_certificate/pkix/rfc7093_method_2.crttest b/tests/integration_certificate/pkix/rfc7093_method_2.crttest new file mode 100644 index 0000000..57a4d11 --- /dev/null +++ b/tests/integration_certificate/pkix/rfc7093_method_2.crttest @@ -0,0 +1,36 @@ +-----BEGIN CERTIFICATE----- +MIIFwjCCA6qgAwIBAgIUH/nOhctN2lspZ2LasyeIMEixJzEwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCVVMxHzAdBgNVBAoMFkZvbyBJbmR1c3RyaWVzIExpbWl0 +ZWQxGDAWBgNVBAMMD0ludGVybWVkaWF0ZSBDQTAeFw0yMzA0MTkwMDAwMDBaFw0y +MzA3MTgyMzU5NTlaME4xIjAgBgNVBAMMGWhhbmFrby55YW1hZGFAZXhhbXBsZS5j +b20xKDAmBgkqhkiG9w0BCQEWGWhhbmFrby55YW1hZGFAZXhhbXBsZS5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCw+egZQ6eumJKq3hfKfED4dE/t +L4FI5sjqont9ABVI+1GSqyi1bFBgsRjM0THllIdMbKmJtWwnKW8J+5OgNN8y6Xxv +8JmM/Y5vQt2lis0fqXmG8UTz0VTWdlAXXmhUs6lSADvAaIe4RVrCsZ97L3ZQTryY +7JRVcbB4khUN3Gp0yg+801SXzoFTTa+UGIRLE66jH51aa5VXu99hnv1OiH8tQrjd +i8mH6uG/icq4XuIeNWMF32wHqIOOPvQcWV3M5D2vxJEj702Ku6k9OQXkAo17qRSE +onWW4HtLbtmS8He1JNPc/n3dVUm+fM6NoDXPoLP7j55G9zKyqGtGAWXAj1MTAgMB +AAGjggGcMIIBmDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAfBgNVHSME +GDAWgBTWRAAyfKgN/6xPa2buta6bLMU4VDAdBgNVHQ4EFgQU3omPCXKXVhKhLmjb +NT6C2kVHzt8wFAYDVR0gBA0wCzAJBgdngQwBBQECMD0GA1UdHwQ2MDQwMqAwoC6G +LGh0dHA6Ly9jcmwuY2EuZXhhbXBsZS5jb20vaXNzdWluZ19jYV9jcmwuY3JsMEsG +CCsGAQUFBwEBBD8wPTA7BggrBgEFBQcwAoYvaHR0cDovL3JlcG9zaXRvcnkuY2Eu +ZXhhbXBsZS5jb20vaXNzdWluZ19jYS5kZXIwHQYDVR0lBBYwFAYIKwYBBQUHAwQG +CCsGAQUFBwMCMHcGA1UdEQRwMG6BGWhhbmFrby55YW1hZGFAZXhhbXBsZS5jb22g +KQYKKwYBBAGCNxQCA6AbDBloYW5ha28ueWFtYWRhQGV4YW1wbGUuY29toCYGCCsG +AQUFBwgJoBoMGOWxseeUsOiKseWtkEBleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsF +AAOCAgEAg4rIcKGMfLh347FX/Y12lx7b9/iVrjsX7lsliirpITuPmfCli76JVrO0 +Fqypfdd2P4ZVvH9WTpQUhRBv06kwHkJRkgpqNPO0WOpNVnsK8vcP1/RylDiJGryz +u6AzOSDqsxomFD6hm71XRYcsgBXXNPUzSGhbqUeuBuZwZe1WmP/yuvNpghMvlWFc +jAHktC9FuNpHhQ/3zZ20GUc6AQwwtn8rviFSwQihVJDJkGiGaJUc7lVVoswx87bS +oGpVluEIY/RK2HsXU0kmek4qq2t9v1OgRL98ZqUgOS26ooOXxqnR3QMx1S5KSLy9 ++hK6y2gPhyiHoaPVTk4s54Es/YDtbCz7piyyyp3DEIzmgrwB/mG2IbOv6dT8Za5B +R7A+ggB7uwo3zYxKd2SFIDmXb+n9ML/s6/3aeyKJms4FmRq+fX8icb+lvVeLMhlC +Re5MFL2tkb72BFku0eeUde4iUnw93fzG6+Wl8VPCzYOwV0j+UTiyygcXaEZW+TpT +EmyY/fQ/7TCbGp+8Ur3rLlY5Okt5T83MmZdMFIHLQxaZUXkT2dBaSnh3VfNKFi0a +re9xdiBQZGkMkvWiKTjrUOwLXSNBnP6TXO9zn51tTK4KPZnQvNvULtn4H7z3FhfW +kie/jPNYkFvMzOaawwPAhG9R6G2ZB7cTOuG0Uu863Hkh5XX2oAo= +-----END CERTIFICATE----- + +node_path,validator,severity,code,message +certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix_subject_key_identifier_rfc7093_method_2_identified, diff --git a/tests/integration_certificate/pkix/rfc7093_method_3.crttest b/tests/integration_certificate/pkix/rfc7093_method_3.crttest new file mode 100644 index 0000000..a2b7ea6 --- /dev/null +++ b/tests/integration_certificate/pkix/rfc7093_method_3.crttest @@ -0,0 +1,36 @@ +-----BEGIN CERTIFICATE----- +MIIFwjCCA6qgAwIBAgIUH/nOhctN2lspZ2LasyeIMEixJzEwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCVVMxHzAdBgNVBAoMFkZvbyBJbmR1c3RyaWVzIExpbWl0 +ZWQxGDAWBgNVBAMMD0ludGVybWVkaWF0ZSBDQTAeFw0yMzA0MTkwMDAwMDBaFw0y +MzA3MTgyMzU5NTlaME4xIjAgBgNVBAMMGWhhbmFrby55YW1hZGFAZXhhbXBsZS5j +b20xKDAmBgkqhkiG9w0BCQEWGWhhbmFrby55YW1hZGFAZXhhbXBsZS5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCw+egZQ6eumJKq3hfKfED4dE/t +L4FI5sjqont9ABVI+1GSqyi1bFBgsRjM0THllIdMbKmJtWwnKW8J+5OgNN8y6Xxv +8JmM/Y5vQt2lis0fqXmG8UTz0VTWdlAXXmhUs6lSADvAaIe4RVrCsZ97L3ZQTryY +7JRVcbB4khUN3Gp0yg+801SXzoFTTa+UGIRLE66jH51aa5VXu99hnv1OiH8tQrjd +i8mH6uG/icq4XuIeNWMF32wHqIOOPvQcWV3M5D2vxJEj702Ku6k9OQXkAo17qRSE +onWW4HtLbtmS8He1JNPc/n3dVUm+fM6NoDXPoLP7j55G9zKyqGtGAWXAj1MTAgMB +AAGjggGcMIIBmDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAfBgNVHSME +GDAWgBTWRAAyfKgN/6xPa2buta6bLMU4VDAdBgNVHQ4EFgQUY8emM7B5J41rU5mX +UlMU8cq/Rg8wFAYDVR0gBA0wCzAJBgdngQwBBQECMD0GA1UdHwQ2MDQwMqAwoC6G +LGh0dHA6Ly9jcmwuY2EuZXhhbXBsZS5jb20vaXNzdWluZ19jYV9jcmwuY3JsMEsG +CCsGAQUFBwEBBD8wPTA7BggrBgEFBQcwAoYvaHR0cDovL3JlcG9zaXRvcnkuY2Eu +ZXhhbXBsZS5jb20vaXNzdWluZ19jYS5kZXIwHQYDVR0lBBYwFAYIKwYBBQUHAwQG +CCsGAQUFBwMCMHcGA1UdEQRwMG6BGWhhbmFrby55YW1hZGFAZXhhbXBsZS5jb22g +KQYKKwYBBAGCNxQCA6AbDBloYW5ha28ueWFtYWRhQGV4YW1wbGUuY29toCYGCCsG +AQUFBwgJoBoMGOWxseeUsOiKseWtkEBleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsF +AAOCAgEAg4rIcKGMfLh347FX/Y12lx7b9/iVrjsX7lsliirpITuPmfCli76JVrO0 +Fqypfdd2P4ZVvH9WTpQUhRBv06kwHkJRkgpqNPO0WOpNVnsK8vcP1/RylDiJGryz +u6AzOSDqsxomFD6hm71XRYcsgBXXNPUzSGhbqUeuBuZwZe1WmP/yuvNpghMvlWFc +jAHktC9FuNpHhQ/3zZ20GUc6AQwwtn8rviFSwQihVJDJkGiGaJUc7lVVoswx87bS +oGpVluEIY/RK2HsXU0kmek4qq2t9v1OgRL98ZqUgOS26ooOXxqnR3QMx1S5KSLy9 ++hK6y2gPhyiHoaPVTk4s54Es/YDtbCz7piyyyp3DEIzmgrwB/mG2IbOv6dT8Za5B +R7A+ggB7uwo3zYxKd2SFIDmXb+n9ML/s6/3aeyKJms4FmRq+fX8icb+lvVeLMhlC +Re5MFL2tkb72BFku0eeUde4iUnw93fzG6+Wl8VPCzYOwV0j+UTiyygcXaEZW+TpT +EmyY/fQ/7TCbGp+8Ur3rLlY5Okt5T83MmZdMFIHLQxaZUXkT2dBaSnh3VfNKFi0a +re9xdiBQZGkMkvWiKTjrUOwLXSNBnP6TXO9zn51tTK4KPZnQvNvULtn4H7z3FhfW +kie/jPNYkFvMzOaawwPAhG9R6G2ZB7cTOuG0Uu863Hkh5XX2oAo= +-----END CERTIFICATE----- + +node_path,validator,severity,code,message +certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix_subject_key_identifier_rfc7093_method_3_identified, diff --git a/tests/integration_certificate/pkix/unknown_skid_method.crttest b/tests/integration_certificate/pkix/unknown_skid_method.crttest new file mode 100644 index 0000000..68e2832 --- /dev/null +++ b/tests/integration_certificate/pkix/unknown_skid_method.crttest @@ -0,0 +1,36 @@ +-----BEGIN CERTIFICATE----- +MIIFwjCCA6qgAwIBAgIUH/nOhctN2lspZ2LasyeIMEixJzEwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCVVMxHzAdBgNVBAoMFkZvbyBJbmR1c3RyaWVzIExpbWl0 +ZWQxGDAWBgNVBAMMD0ludGVybWVkaWF0ZSBDQTAeFw0yMzA0MTkwMDAwMDBaFw0y +MzA3MTgyMzU5NTlaME4xIjAgBgNVBAMMGWhhbmFrby55YW1hZGFAZXhhbXBsZS5j +b20xKDAmBgkqhkiG9w0BCQEWGWhhbmFrby55YW1hZGFAZXhhbXBsZS5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCw+egZQ6eumJKq3hfKfED4dE/t +L4FI5sjqont9ABVI+1GSqyi1bFBgsRjM0THllIdMbKmJtWwnKW8J+5OgNN8y6Xxv +8JmM/Y5vQt2lis0fqXmG8UTz0VTWdlAXXmhUs6lSADvAaIe4RVrCsZ97L3ZQTryY +7JRVcbB4khUN3Gp0yg+801SXzoFTTa+UGIRLE66jH51aa5VXu99hnv1OiH8tQrjd +i8mH6uG/icq4XuIeNWMF32wHqIOOPvQcWV3M5D2vxJEj702Ku6k9OQXkAo17qRSE +onWW4HtLbtmS8He1JNPc/n3dVUm+fM6NoDXPoLP7j55G9zKyqGtGAWXAj1MTAgMB +AAGjggGcMIIBmDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAfBgNVHSME +GDAWgBTWRAAyfKgN/6xPa2buta6bLMU4VDAdBgNVHQ4EFgQUY8emM7B5J41rU5mX +UlMU8cq/Rg4wFAYDVR0gBA0wCzAJBgdngQwBBQECMD0GA1UdHwQ2MDQwMqAwoC6G +LGh0dHA6Ly9jcmwuY2EuZXhhbXBsZS5jb20vaXNzdWluZ19jYV9jcmwuY3JsMEsG +CCsGAQUFBwEBBD8wPTA7BggrBgEFBQcwAoYvaHR0cDovL3JlcG9zaXRvcnkuY2Eu +ZXhhbXBsZS5jb20vaXNzdWluZ19jYS5kZXIwHQYDVR0lBBYwFAYIKwYBBQUHAwQG +CCsGAQUFBwMCMHcGA1UdEQRwMG6BGWhhbmFrby55YW1hZGFAZXhhbXBsZS5jb22g +KQYKKwYBBAGCNxQCA6AbDBloYW5ha28ueWFtYWRhQGV4YW1wbGUuY29toCYGCCsG +AQUFBwgJoBoMGOWxseeUsOiKseWtkEBleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsF +AAOCAgEAg4rIcKGMfLh347FX/Y12lx7b9/iVrjsX7lsliirpITuPmfCli76JVrO0 +Fqypfdd2P4ZVvH9WTpQUhRBv06kwHkJRkgpqNPO0WOpNVnsK8vcP1/RylDiJGryz +u6AzOSDqsxomFD6hm71XRYcsgBXXNPUzSGhbqUeuBuZwZe1WmP/yuvNpghMvlWFc +jAHktC9FuNpHhQ/3zZ20GUc6AQwwtn8rviFSwQihVJDJkGiGaJUc7lVVoswx87bS +oGpVluEIY/RK2HsXU0kmek4qq2t9v1OgRL98ZqUgOS26ooOXxqnR3QMx1S5KSLy9 ++hK6y2gPhyiHoaPVTk4s54Es/YDtbCz7piyyyp3DEIzmgrwB/mG2IbOv6dT8Za5B +R7A+ggB7uwo3zYxKd2SFIDmXb+n9ML/s6/3aeyKJms4FmRq+fX8icb+lvVeLMhlC +Re5MFL2tkb72BFku0eeUde4iUnw93fzG6+Wl8VPCzYOwV0j+UTiyygcXaEZW+TpT +EmyY/fQ/7TCbGp+8Ur3rLlY5Okt5T83MmZdMFIHLQxaZUXkT2dBaSnh3VfNKFi0a +re9xdiBQZGkMkvWiKTjrUOwLXSNBnP6TXO9zn51tTK4KPZnQvNvULtn4H7z3FhfW +kie/jPNYkFvMzOaawwPAhG9R6G2ZB7cTOuG0Uu863Hkh5XX2oAo= +-----END CERTIFICATE----- + +node_path,validator,severity,code,message +certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,NOTICE,pkix.unknown_subject_key_identifier_calculation_method, From 5049df01fb8c93dad004e8508f92eec170da4d26 Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Fri, 15 Dec 2023 16:49:20 -0500 Subject: [PATCH 4/6] Update changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c93078..b26d044 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ All notable changes to this project from version 0.9.3 onwards are documented in this file. +## 0.9.9 - 2023-12-18 + +### Fixes + +- SaneValidityPeriodValidator incorrectly reports "pkix.invalid_time_syntax" for negative validity periods (#57) +- Decoder mapping for QcCompliance and QcSSCD statements incorrectly mapped to None (#58) + +### New features/enhancements + +- Add detection of SKI calculation methods described in RFC 7093 to SubjectKeyIdentifierValidator (#56) + ## 0.9.8 - 2023-11-21 ### Fixes From bde3fc1484923c38967df4651a39e2835670bd76 Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Fri, 15 Dec 2023 17:03:53 -0500 Subject: [PATCH 5/6] Fix SKI finding codes --- pkilint/pkix/certificate/certificate_key.py | 6 +++--- tests/integration_certificate/pkix/rfc7093_method_1.crttest | 2 +- tests/integration_certificate/pkix/rfc7093_method_2.crttest | 2 +- tests/integration_certificate/pkix/rfc7093_method_3.crttest | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkilint/pkix/certificate/certificate_key.py b/pkilint/pkix/certificate/certificate_key.py index 94ac70a..d1f744e 100644 --- a/pkilint/pkix/certificate/certificate_key.py +++ b/pkilint/pkix/certificate/certificate_key.py @@ -123,17 +123,17 @@ class SubjectKeyIdentifierValidator(validation.Validator): VALIDATION_RFC7093_METHOD_1 = validation.ValidationFinding( validation.ValidationFindingSeverity.INFO, - 'pkix_subject_key_identifier_rfc7093_method_1_identified' + 'pkix.subject_key_identifier_rfc7093_method_1_identified' ) VALIDATION_RFC7093_METHOD_2 = validation.ValidationFinding( validation.ValidationFindingSeverity.INFO, - 'pkix_subject_key_identifier_rfc7093_method_2_identified' + 'pkix.subject_key_identifier_rfc7093_method_2_identified' ) VALIDATION_RFC7093_METHOD_3 = validation.ValidationFinding( validation.ValidationFindingSeverity.INFO, - 'pkix_subject_key_identifier_rfc7093_method_3_identified' + 'pkix.subject_key_identifier_rfc7093_method_3_identified' ) def __init__(self): diff --git a/tests/integration_certificate/pkix/rfc7093_method_1.crttest b/tests/integration_certificate/pkix/rfc7093_method_1.crttest index 45f91f6..93eaa86 100644 --- a/tests/integration_certificate/pkix/rfc7093_method_1.crttest +++ b/tests/integration_certificate/pkix/rfc7093_method_1.crttest @@ -17,4 +17,4 @@ AZvTbDmzq9nfzN4wz4KGkMuy0Ab7nuguoYht4LNEZG/M+uz3eh6rCEzoxIoy8w== -----END CERTIFICATE----- node_path,validator,severity,code,message -certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix_subject_key_identifier_rfc7093_method_1_identified +certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix.subject_key_identifier_rfc7093_method_1_identified diff --git a/tests/integration_certificate/pkix/rfc7093_method_2.crttest b/tests/integration_certificate/pkix/rfc7093_method_2.crttest index 57a4d11..679d9ac 100644 --- a/tests/integration_certificate/pkix/rfc7093_method_2.crttest +++ b/tests/integration_certificate/pkix/rfc7093_method_2.crttest @@ -33,4 +33,4 @@ kie/jPNYkFvMzOaawwPAhG9R6G2ZB7cTOuG0Uu863Hkh5XX2oAo= -----END CERTIFICATE----- node_path,validator,severity,code,message -certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix_subject_key_identifier_rfc7093_method_2_identified, +certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix.subject_key_identifier_rfc7093_method_2_identified, diff --git a/tests/integration_certificate/pkix/rfc7093_method_3.crttest b/tests/integration_certificate/pkix/rfc7093_method_3.crttest index a2b7ea6..f1ae5d9 100644 --- a/tests/integration_certificate/pkix/rfc7093_method_3.crttest +++ b/tests/integration_certificate/pkix/rfc7093_method_3.crttest @@ -33,4 +33,4 @@ kie/jPNYkFvMzOaawwPAhG9R6G2ZB7cTOuG0Uu863Hkh5XX2oAo= -----END CERTIFICATE----- node_path,validator,severity,code,message -certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix_subject_key_identifier_rfc7093_method_3_identified, +certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix.subject_key_identifier_rfc7093_method_3_identified, From dba2d0118ae4eb2a251ccff2917c5da6108ad9b7 Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Mon, 18 Dec 2023 08:38:18 -0500 Subject: [PATCH 6/6] Update finding metadata CSVs --- pkilint/cabf/serverauth/finding_metadata.csv | 3 +++ pkilint/cabf/smime/finding_metadata.csv | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkilint/cabf/serverauth/finding_metadata.csv b/pkilint/cabf/serverauth/finding_metadata.csv index be273c0..c44f9ce 100644 --- a/pkilint/cabf/serverauth/finding_metadata.csv +++ b/pkilint/cabf/serverauth/finding_metadata.csv @@ -308,3 +308,6 @@ NOTICE,pkix.ldap_uri_not_validated,": Notice that the linter encountered a LDAP NOTICE,pkix.unknown_subject_key_identifier_calculation_method,RFC 5280 4.2.1.2: The Subject key identifier was not calculated using one of the algorithms defined in RFC 5280 INFO,pkix.subject_key_identifier_method_1_identified,RFC 5280 4.2.1.2: The Subject key identifier was calculated using the first algorithm defined in RFC 5280 INFO,pkix.subject_key_identifier_method_2_identified,RFC 5280 4.2.1.2: The Subject key identifier was calculated using the second algorithm defined in RFC 5280 +INFO,pkix.subject_key_identifier_rfc7093_method_1_identified,"RFC 7093 2: The keyIdentifier is composed of the leftmost 160-bits of the SHA-256 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits)." +INFO,pkix.subject_key_identifier_rfc7093_method_2_identified,"RFC 7093 2: The keyIdentifier is composed of the leftmost 160-bits of the SHA-384 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits)." +INFO,pkix.subject_key_identifier_rfc7093_method_3_identified,"RFC 7093 2: The keyIdentifier is composed of the leftmost 160-bits of the SHA-512 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits)." diff --git a/pkilint/cabf/smime/finding_metadata.csv b/pkilint/cabf/smime/finding_metadata.csv index cff5049..75c258d 100644 --- a/pkilint/cabf/smime/finding_metadata.csv +++ b/pkilint/cabf/smime/finding_metadata.csv @@ -23,7 +23,7 @@ ERROR,cabf.smime.adobe_timestamp_extension_critical,SMBR 7.1.2.3 (m),"""MAY be p ERROR,cabf.smime.adobe_timestamp_extension_prohibited,SMBR 7.1.2.3 (m),"""Strict: prohibited""" ERROR,cabf.smime.aia_prohibited_generalname_type,SMBR 7.1.2.3 (c),"""Allowed URI scheme""" ERROR,cabf.smime.aia_prohibited_uri_scheme,SMBR 7.1.2.3 (c),"Legacy: ""When provided, at least one accessMethod SHALL have the URI scheme HTTP"". MP and strict: ""When provided, every accessMethod SHALL have the URI scheme HTTP""" -ERROR,cabf.smime.anypolicy_present,"An end-entity S/MIME certificate contains the anyPolicy policy identifier" +ERROR,cabf.smime.anypolicy_present,An end-entity S/MIME certificate contains the anyPolicy policy identifier, ERROR,cabf.smime.certificate_policies_extension_missing,SMBR 7.1.2.3 (a),"""SHALL be present""" ERROR,cabf.smime.certificate_validity_period_exceeds_1185_days,SMBR 6.2.3,"""Legacy: 1185 days""" ERROR,cabf.smime.common_name_value_unknown_source,SMBR 7.1.4.2.2 (a),Common name attribute contains a value that does not correspond to any allowed value in the table in 7.1.4.2.2 (a) @@ -107,7 +107,7 @@ ERROR,pkix.rdn_contains_unique_attribute_types,X.501 1997-08 9.3,"""The set that ERROR,pkix.rfc5280_certificate_policies_invalid_explicit_text_encoding,RFC 5280 4.2.1.4,"""Conforming CAs MUST NOT encode explicitText as VisibleString or BMPString.""" ERROR,pkix.rfc6818_certificate_policies_invalid_explicit_text_encoding,RFC 6818 3,"""Conforming CAs MUST NOT encode explicitText as IA5String""" ERROR,pkix.san_extension_not_critical,RFC 5280 4.2.1.6,"""If the subject field contains an empty sequence, then the issuing CA MUST include a subjectAltName extension that is marked as critical""" -ERROR,pkix.sct_list_empty,"RFC 6962 3.3: ""At least one SCT MUST be included""" +ERROR,pkix.sct_list_empty,"RFC 6962 3.3: ""At least one SCT MUST be included""", ERROR,pkix.smime_capabilities_extension_critical,RFC 4262 2,"""This extension MUST NOT be marked critical.""" ERROR,pkix.smtp_utf8_mailbox_has_bom,RFC 8398 3,"""The UTF8String encoding MUST NOT contain a Byte-Order-Mark (BOM) [RFC3629] to aid consistency across implementations, particularly for comparison.""" ERROR,pkix.smtp_utf8_mailbox_has_uppercase,RFC 8398 3,"""In SmtpUTF8Mailbox, domain labels that solely use ASCII characters (meaning neither A- nor U-labels) SHALL use NR-LDH restrictions as specified by Section 2.3.1 of [RFC5890] and SHALL be restricted to lowercase letters.""" @@ -147,3 +147,6 @@ NOTICE,pkix.ldap_uri_not_validated,,"Notice that the linter encountered a LDAP U NOTICE,pkix.unknown_subject_key_identifier_calculation_method,RFC 5280 4.2.1.2,The Subject key identifier was not calculated using one of the algorithms defined in RFC 5280 INFO,pkix.subject_key_identifier_method_1_identified,RFC 5280 4.2.1.2,The Subject key identifier was calculated using the first algorithm defined in RFC 5280 INFO,pkix.subject_key_identifier_method_2_identified,RFC 5280 4.2.1.2,The Subject key identifier was calculated using the second algorithm defined in RFC 5280 +INFO,pkix.subject_key_identifier_rfc7093_method_1_identified,RFC 7093 2,"The keyIdentifier is composed of the leftmost 160-bits of the SHA-256 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits)." +INFO,pkix.subject_key_identifier_rfc7093_method_2_identified,"RFC 7093 2: The keyIdentifier is composed of the leftmost 160-bits of the SHA-384 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits).","The keyIdentifier is composed of the leftmost 160-bits of the SHA-384 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits)." +INFO,pkix.subject_key_identifier_rfc7093_method_3_identified,"RFC 7093 2: The keyIdentifier is composed of the leftmost 160-bits of the SHA-512 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits).","The keyIdentifier is composed of the leftmost 160-bits of the SHA-512 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits)."