Skip to content

Commit

Permalink
Add prohibition on issuance of legacy generation S/MIME certificates
Browse files Browse the repository at this point in the history
  • Loading branch information
CBonnell committed Aug 28, 2024
1 parent 320b7b0 commit 7d5e2bc
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 9 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

All notable changes to this project from version 0.9.3 onwards are documented in this file.

## 0.11.4 - 2024-08-28
## 0.11.4 - 2024-08-29

### New features/enhancements

- Use pyasn1-fasder for ASN.1 DER decoding by default (#98)
- Add support for S/MIME working group ballot SMC-08 (#101)

## 0.11.3 - 2024-07-17

Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,13 @@ For example, the following mapping file is used to map policy OID `1.2.3.4.5.6`
The `-o`/`--output` option is used to specify that the validation level and generation used by the linter is written to standard error. This is useful when using the `--guess` option to see which validation level and generation was determined by the heuristics logic.
The `--validity-period-start` option is used to override how the issuance date/time of a certificate is determined. Many requirements are applicable based on the date/time of issuance of certificates, so this option is useful
to evaluate whether a certificate complies with an upcoming requirement. There are three possible types of values for this option:
1. `DOCUMENT`: Use the value of the `notBefore` field to determine the issuance date/time. This is the default value.
2. `NOW`: Use the current date/time to override the issuance date/time.
3. An ISO 8601 timestamp: Use the specified timestamp to override the issuance date/time.
#### Example command execution
```shell
Expand Down
4 changes: 3 additions & 1 deletion pkilint/bin/lint_cabf_smime_cert.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ def main(cli_args=None) -> int:
help='Output the type of S/MIME certificate to standard error. This option may be '
'useful when using the --detect, --guess, or --mapping options.')

util.add_certificate_validity_period_start_arg(lint_parser)

util.add_standard_args(lint_parser)

lint_parser.add_argument('file',
Expand Down Expand Up @@ -142,7 +144,7 @@ def main(cli_args=None) -> int:
doc_validator = certificate.create_pkix_certificate_validator_container(
smime.create_decoding_validators(),
smime.create_subscriber_validators(
validation_level, generation
validation_level, generation, args.validity_period_start
)
)

Expand Down
26 changes: 20 additions & 6 deletions pkilint/cabf/smime/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import operator
from typing import Mapping, Tuple
from typing import Mapping, Tuple, Optional

from dateutil.relativedelta import relativedelta
from pyasn1.type import univ
Expand All @@ -15,14 +15,15 @@
from pkilint.adobe import adobe_validator
from pkilint.cabf import cabf_extension, cabf_key, cabf_name
from pkilint.cabf.smime import (
smime_constants, smime_name, smime_key, smime_extension
smime_constants, smime_name, smime_key, smime_extension, smime_validity
)
from pkilint.cabf.smime.smime_constants import Generation
from pkilint.common import alternative_name
from pkilint.iso import lei
from pkilint.msft import asn1 as microsoft_asn1
from pkilint.msft import msft_name
from pkilint.pkix import certificate, time
from pkilint.pkix.certificate import certificate_validity
from pkilint.pkix.general_name import OTHER_NAME_MAPPINGS as PKIX_OTHERNAME_MAPPINGS

OTHER_NAME_MAPPINGS = {
Expand Down Expand Up @@ -192,7 +193,7 @@ def create_extensions_validator_container(validation_level, generation):
)


def create_validity_validators(generation):
def create_validity_validators(generation, validity_period_start_retriever: document.ValidityPeriodStartRetriever):
days = 1185 if generation == Generation.LEGACY else 825

threshold_error = (
Expand All @@ -212,7 +213,8 @@ def create_validity_validators(generation):
'cabf.smime.certificate_validity_period_at_maximum'
)
)
return [

validators = [
time.ValidityPeriodThresholdsValidator(
path='certificate.tbsCertificate.validity.notBefore',
end_validity_node_retriever=lambda n: n.navigate('^.notAfter'),
Expand All @@ -221,16 +223,28 @@ def create_validity_validators(generation):
)
]

if generation == smime_constants.Generation.LEGACY:
validators.append(smime_validity.LegacyGenerationSunsetValidator(validity_period_start_retriever))

return validators


def create_subscriber_validators(
validation_level,
generation,
validity_period_start_retriever: Optional[document.ValidityPeriodStartRetriever] = None
):
if validity_period_start_retriever is None:
validity_period_start_retriever = certificate_validity.CertificateValidityPeriodStartRetriever()

def create_subscriber_validators(validation_level, generation):
return [
smime_name.create_subscriber_certificate_subject_validator_container(validation_level, generation),
create_spki_validation_container(),
certificate.create_issuer_validator_container(
[]
),
certificate.create_validity_validator_container(
create_validity_validators(generation)
create_validity_validators(generation, validity_period_start_retriever)
),
create_extensions_validator_container(validation_level, generation),
smime_key.SmimeAllowedSignatureAlgorithmEncodingValidator(
Expand Down
1 change: 1 addition & 0 deletions pkilint/cabf/smime/finding_metadata.csv
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ ERROR,cabf.smime.extended_key_usage_extension_missing,SMBR 7.1.2.3 (f),"""SHALL
ERROR,cabf.smime.invalid_lei_scheme_format,SMBR 7.1.4.2.2 (d) and SMBR 7.1.2.3 (l),LEI value does not conform to standard LEI format (20 alphanumeric characters)
ERROR,cabf.smime.is_ca_certificate,SMBR 7.1.2.3 (d),"""The cA field SHALL NOT be true"""
ERROR,cabf.smime.key_usage_extension_missing,SMBR 7.1.2.3 (e),"""SHALL be present"""
ERROR,cabf.smime.legacy_generation_certificate_issued_after_prohibition,SMBR 7.1.6.1,"Effective July 15, 2025 S/MIME Subscriber Certificates SHALL NOT be issued using the Legacy Generation profiles 2.23.140.1.5.1.1, 2.23.140.1.5.2.1, 2.23.140.1.5.3.1, or 2.23.140.1.5.4.1."
ERROR,cabf.smime.lei_extension_critical,SMBR 7.1.2.3 (l),""" SHALL NOT be marked critical"""
ERROR,cabf.smime.lei_extension_prohibited,SMBR 7.1.2.3 (l),Mailbox- and individual-validated: Prohibited
ERROR,cabf.smime.lei_role_extension_critical,SMBR 7.1.2.3 (l),"""SHALL NOT be marked critical"""
Expand Down
2 changes: 1 addition & 1 deletion pkilint/cabf/smime/smime_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pyasn1.type.univ import ObjectIdentifier


BR_VERSION = '1.0.4'
BR_VERSION = '1.0.6'


CABF_SMIME_OID_ARC = ObjectIdentifier('2.23.140.1.5')
Expand Down
28 changes: 28 additions & 0 deletions pkilint/cabf/smime/smime_validity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import datetime

from pyasn1_alt_modules import rfc5280

from pkilint import validation, document


class LegacyGenerationSunsetValidator(validation.Validator):
VALIDATION_LEGACY_GENERATION_CERTIFICATE_ISSUED_AFTER_PROHIBITION = validation.ValidationFinding(
validation.ValidationFindingSeverity.ERROR,
'cabf.smime.legacy_generation_certificate_issued_after_prohibition'
)

_LEGACY_GENERATION_SUNSET_DATE = datetime.datetime(2025, 7, 15, 0, 0, 0, tzinfo=datetime.timezone.utc)

def __init__(self, validity_period_start_retriever: document.ValidityPeriodStartRetriever):
super().__init__(
validations=[self.VALIDATION_LEGACY_GENERATION_CERTIFICATE_ISSUED_AFTER_PROHIBITION],
pdu_class=rfc5280.Validity
)

self._validity_period_start_retriever = validity_period_start_retriever

def validate(self, node):
if self._validity_period_start_retriever(node.document) >= self._LEGACY_GENERATION_SUNSET_DATE:
raise validation.ValidationFindingEncountered(
self.VALIDATION_LEGACY_GENERATION_CERTIFICATE_ISSUED_AFTER_PROHIBITION
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
-----BEGIN CERTIFICATE-----
MIIF1DCCA7ygAwIBAgIUL745jJJYnvMFGPE42o7ukLDYP/IwDQYJKoZIhvcNAQEL
BQAwSDELMAkGA1UEBhMCVVMxHzAdBgNVBAoMFkZvbyBJbmR1c3RyaWVzIExpbWl0
ZWQxGDAWBgNVBAMMD0ludGVybWVkaWF0ZSBDQTAeFw0yNjA0MjgwMDAwMDBaFw0y
NzA3MjcyMzU5NTlaMEIxFjAUBgNVBAMMDVlBTUFEQSBIYW5ha28xKDAmBgkqhkiG
9w0BCQEWGWhhbmFrby55YW1hZGFAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQCw+egZQ6eumJKq3hfKfED4dE/tL4FI5sjqont9ABVI
+1GSqyi1bFBgsRjM0THllIdMbKmJtWwnKW8J+5OgNN8y6Xxv8JmM/Y5vQt2lis0f
qXmG8UTz0VTWdlAXXmhUs6lSADvAaIe4RVrCsZ97L3ZQTryY7JRVcbB4khUN3Gp0
yg+801SXzoFTTa+UGIRLE66jH51aa5VXu99hnv1OiH8tQrjdi8mH6uG/icq4XuIe
NWMF32wHqIOOPvQcWV3M5D2vxJEj702Ku6k9OQXkAo17qRSEonWW4HtLbtmS8He1
JNPc/n3dVUm+fM6NoDXPoLP7j55G9zKyqGtGAWXAj1MTAgMBAAGjggG6MIIBtjAM
BgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAfBgNVHSMEGDAWgBTWRAAyfKgN
/6xPa2buta6bLMU4VDAdBgNVHQ4EFgQUiRlZXg7xafXLvUfhNPzimMxpMJEwFAYD
VR0gBA0wCzAJBgdngQwBBQQBMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jcmwu
Y2EuZXhhbXBsZS5jb20vaXNzdWluZ19jYV9jcmwuY3JsMEsGCCsGAQUFBwEBBD8w
PTA7BggrBgEFBQcwAoYvaHR0cDovL3JlcG9zaXRvcnkuY2EuZXhhbXBsZS5jb20v
aXNzdWluZ19jYS5kZXIwHQYDVR0lBBYwFAYIKwYBBQUHAwQGCCsGAQUFBwMCMIGU
BgNVHREEgYwwgYmBGWhhbmFrby55YW1hZGFAZXhhbXBsZS5jb22gKQYKKwYBBAGC
NxQCA6AbDBloYW5ha28ueWFtYWRhQGV4YW1wbGUuY29toCYGCCsGAQUFBwgJoBoM
GOWxseeUsOiKseWtkEBleGFtcGxlLmNvbaQZMBcxFTATBgNVBAMMDOWxseeUsOiK
seWtkDANBgkqhkiG9w0BAQsFAAOCAgEAjEOEra5mkkzlUePGTbMa8KoXh7eo/xfx
8SzPuE6HF4O6kCmh6AD1bq0T2ahLYwniSOtE3iBg9KhauALzjqYL+ko0JkvmIRLN
BHGS3UNDMz5FW8+7+coU4MwlVuQUOyt9t01ZkbOBx5FkLupcONYcbAuY4gGPUEcu
kjyCQnIA6LjlqCtD9DhIjFr7f7DFsMXP2iNXBQs/TgZwxX+OIb9JIhkDhEPy0kou
5p7hzbJwnveA7cKxLUx9LuYBln65VB4iBdLjHRwbnc7LVOx9oZk/V9yNg/h3UjfB
L6MH6Kgac7o2dkdnH9yGTrhCkt9K09tzmi3ODv1bxjUbojzGDJbVC2YQ6HMntn88
9S98J461+qYfZuxIoFp1HCXtJs1iZ2HPuz7sma+vUtd9s4S9OWGruyDkxZlClcZ+
IgH7MZYnvByo3XZd+c3jk6692bqEYBgvu5tWrId4h9hVh7TY4pbKwwZnFojPLkHH
2OMkjJqK54R/PS3Ea0V8vInxwr8ESmLo/DZUuUNaX82UOkOXd2wwhHexlVtZM5Hs
IVDZxDulQS1lll+M6vAzHq9buxAdkRAiyC5X+dSqkP5itNCQBkJrnfi8tVfHg69X
APeclV11R1Ksnjn6OjwAKBmWnU99HzScksMx0SOI5G99+6mzz3zZLVQdPlnSj5V+
tgkVdJ0YdSw=
-----END CERTIFICATE-----

node_path,validator,severity,code,message
certificate.tbsCertificate.validity,LegacyGenerationSunsetValidator,ERROR,cabf.smime.legacy_generation_certificate_issued_after_prohibition,
certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix.subject_key_identifier_method_1_identified,

0 comments on commit 7d5e2bc

Please sign in to comment.