Source code for django_ca.constants

# This file is part of django-ca (https://github.com/mathiasertl/django-ca).
#
# django-ca is free software: you can redistribute it and/or modify it under the terms of the GNU
# General Public License as published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# django-ca is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with django-ca.  If not,
# see <http://www.gnu.org/licenses/>.

"""Collection of constants used by django-ca."""

import enum
from collections import defaultdict
from types import MappingProxyType

from cryptography import x509
from cryptography.x509.certificate_transparency import LogEntryType
from cryptography.x509.oid import ExtendedKeyUsageOID as _ExtendedKeyUsageOID
from cryptography.x509.oid import ExtensionOID

from django.utils.translation import gettext_lazy as _


[docs]class ExtendedKeyUsageOID(_ExtendedKeyUsageOID): """Extend the OIDs known to cryptography with what users needed over the years.""" # Defined in RFC 3280, occurs in TrustID Server A52 CA IPSEC_END_SYSTEM = x509.ObjectIdentifier("1.3.6.1.5.5.7.3.5") IPSEC_TUNNEL = x509.ObjectIdentifier("1.3.6.1.5.5.7.3.6") IPSEC_USER = x509.ObjectIdentifier("1.3.6.1.5.5.7.3.7") # Used by PKINIT logon on Windows (see github #46) SMARTCARD_LOGON = x509.ObjectIdentifier("1.3.6.1.4.1.311.20.2.2") # mobilee Driving Licence or mDL (see ISO/IEC DIS 18013-5, GitHub PR #81) MDL_DOCUMENT_SIGNER = x509.ObjectIdentifier("1.0.18013.5.1.2") MDL_JWS_CERTIFICATE = x509.ObjectIdentifier("1.0.18013.5.1.3") # ExtendedKeyUsageOID.CERTIFICATE_TRANSPARENCY was added in cryptography==39.0 # once support for cryptography<39.0 is dropped. if not hasattr(_ExtendedKeyUsageOID, "CERTIFICATE_TRANSPARENCY"): # pragma: cryptography<38.0 branch CERTIFICATE_TRANSPARENCY = x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.4") # ExtendedKeyUsageOID.IPSEC_IKE was added in cryptography==37.0.0. if not hasattr(_ExtendedKeyUsageOID, "IPSEC_IKE"): # pragma: cryptography<37.0 branch IPSEC_IKE = x509.ObjectIdentifier("1.3.6.1.5.5.7.3.17")
#: Map of ExtendedKeyUsageOIDs to names in RFC 5280 (and other RFCs). EXTENDED_KEY_USAGE_NAMES = MappingProxyType( { ExtendedKeyUsageOID.ANY_EXTENDED_KEY_USAGE: "anyExtendedKeyUsage", ExtendedKeyUsageOID.CERTIFICATE_TRANSPARENCY: "certificateTransparency", ExtendedKeyUsageOID.CLIENT_AUTH: "clientAuth", ExtendedKeyUsageOID.CODE_SIGNING: "codeSigning", ExtendedKeyUsageOID.EMAIL_PROTECTION: "emailProtection", ExtendedKeyUsageOID.IPSEC_END_SYSTEM: "ipsecEndSystem", ExtendedKeyUsageOID.IPSEC_IKE: "ipsecIKE", ExtendedKeyUsageOID.IPSEC_TUNNEL: "ipsecTunnel", ExtendedKeyUsageOID.IPSEC_USER: "ipsecUser", ExtendedKeyUsageOID.KERBEROS_PKINIT_KDC: "msKDC", ExtendedKeyUsageOID.MDL_DOCUMENT_SIGNER: "mdlDS", ExtendedKeyUsageOID.MDL_JWS_CERTIFICATE: "mdlJWS", ExtendedKeyUsageOID.OCSP_SIGNING: "OCSPSigning", ExtendedKeyUsageOID.SERVER_AUTH: "serverAuth", ExtendedKeyUsageOID.SMARTCARD_LOGON: "smartcardLogon", ExtendedKeyUsageOID.TIME_STAMPING: "timeStamping", } ) #: Map of ExtendedKeyUsageOIDs to human readable names. EXTENDED_KEY_USAGE_HUMAN_READABLE_NAMES = MappingProxyType( { ExtendedKeyUsageOID.ANY_EXTENDED_KEY_USAGE: "Any Extended Key Usage", ExtendedKeyUsageOID.CERTIFICATE_TRANSPARENCY: "Certificate Transparency", ExtendedKeyUsageOID.CLIENT_AUTH: "SSL/TLS Web Client Authentication", ExtendedKeyUsageOID.CODE_SIGNING: "Code signing", ExtendedKeyUsageOID.EMAIL_PROTECTION: "E-mail Protection (S/MIME)", ExtendedKeyUsageOID.IPSEC_END_SYSTEM: "IPSec EndSystem", ExtendedKeyUsageOID.IPSEC_IKE: "IPSec Internet Key Exchange", ExtendedKeyUsageOID.IPSEC_TUNNEL: "IPSec Tunnel", ExtendedKeyUsageOID.IPSEC_USER: "IPSec User", ExtendedKeyUsageOID.KERBEROS_PKINIT_KDC: "Kerberos Domain Controller", ExtendedKeyUsageOID.MDL_DOCUMENT_SIGNER: "mdlDS", ExtendedKeyUsageOID.MDL_JWS_CERTIFICATE: "mdlJWS", ExtendedKeyUsageOID.OCSP_SIGNING: "OCSP Signing", ExtendedKeyUsageOID.SERVER_AUTH: "SSL/TLS Web Server Authentication", ExtendedKeyUsageOID.SMARTCARD_LOGON: "Smart card logon", ExtendedKeyUsageOID.TIME_STAMPING: "Trusted Timestamping", } ) #: Map of ExtensionOIDs to a human-readable text describing if the extension should/must/... be critical. EXTENSION_CRITICAL_HELP = MappingProxyType( { ExtensionOID.AUTHORITY_INFORMATION_ACCESS: _("MUST be non-critical"), ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _("MUST be non-critical"), ExtensionOID.BASIC_CONSTRAINTS: _("MUST usually be critical, but allows non-critical in some cases"), ExtensionOID.CERTIFICATE_POLICIES: _("may or may not be critical (recommended: non-critical)"), ExtensionOID.CRL_DISTRIBUTION_POINTS: _("SHOULD be non-critical"), ExtensionOID.CRL_NUMBER: _("is non-critical"), ExtensionOID.DELTA_CRL_INDICATOR: _("is critical"), ExtensionOID.EXTENDED_KEY_USAGE: _("MAY, at your discretion, be either critical or non-critical"), ExtensionOID.FRESHEST_CRL: _("MUST be non-critical"), ExtensionOID.INHIBIT_ANY_POLICY: _("MUST be critical"), ExtensionOID.ISSUER_ALTERNATIVE_NAME: _("SHOULD be non-critical"), ExtensionOID.ISSUING_DISTRIBUTION_POINT: _("is critical"), ExtensionOID.KEY_USAGE: _("SHOULD be critical"), ExtensionOID.NAME_CONSTRAINTS: _("MUST be critical"), ExtensionOID.OCSP_NO_CHECK: _("SHOULD be a non-critical"), # defined in RFC 2560 ExtensionOID.POLICY_CONSTRAINTS: _("MUST be critical"), ExtensionOID.POLICY_MAPPINGS: _("SHOULD be critical"), ExtensionOID.PRECERT_POISON: _("MUST be critical"), # defined in RFC 6962 ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: _( # defined in RFC 6962 "may or may not be critical (recommended: non-critical)" ), ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: _( # defined in RFC 6962 "may or may not be critical (recommended: non-critical)" ), ExtensionOID.SUBJECT_ALTERNATIVE_NAME: _("SHOULD mark this extension as non-critical"), ExtensionOID.SUBJECT_INFORMATION_ACCESS: _("MUST be non-critical"), ExtensionOID.SUBJECT_KEY_IDENTIFIER: _("MUST be non-critical"), ExtensionOID.TLS_FEATURE: _("SHOULD NOT be critical"), # defined in RFC 7633 ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: _("MUST be non-critical"), } ) #: Map of ExtensionOIDs to the default critical values as defined in the RFC where they are defined. EXTENSION_DEFAULT_CRITICAL = MappingProxyType( { ExtensionOID.AUTHORITY_INFORMATION_ACCESS: False, # MUST mark this extension as non-critical. ExtensionOID.AUTHORITY_KEY_IDENTIFIER: False, # MUST mark this extension as non-critical ExtensionOID.BASIC_CONSTRAINTS: True, # RFC 5280 is more complex here, True is a good efault ExtensionOID.CERTIFICATE_POLICIES: False, # RFC 5280 does not say (!) ExtensionOID.CRL_DISTRIBUTION_POINTS: False, # The extension SHOULD be non-critical ExtensionOID.CRL_NUMBER: False, # is a non-critical CRL extension ExtensionOID.DELTA_CRL_INDICATOR: True, # is a critical CRL extension ExtensionOID.EXTENDED_KEY_USAGE: False, # at issuers discretion, but non-critical in the real world. ExtensionOID.FRESHEST_CRL: False, # MUST be marked as non-critical ExtensionOID.INHIBIT_ANY_POLICY: True, # MUST mark this extension as critical ExtensionOID.ISSUER_ALTERNATIVE_NAME: False, # SHOULD mark this extension as non-critical. ExtensionOID.ISSUING_DISTRIBUTION_POINT: True, # is a critical CRL extension ExtensionOID.KEY_USAGE: True, # SHOULD mark this extension as critical. ExtensionOID.NAME_CONSTRAINTS: True, # MUST mark this extension as critical ExtensionOID.OCSP_NO_CHECK: False, # RFC 2560: SHOULD be a non-critical ExtensionOID.POLICY_CONSTRAINTS: True, # MUST mark this extension as critical ExtensionOID.POLICY_MAPPINGS: True, # SHOULD mark this extension as critical ExtensionOID.PRECERT_POISON: True, # RFC 6962: "critical poison extension" ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: False, # RFC 6962 doesn't say ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: False, # RFC 6962 doesn't say ExtensionOID.SUBJECT_ALTERNATIVE_NAME: False, # SHOULD mark the extension as non-critical. ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: False, # MUST mark this extension as non-critical ExtensionOID.SUBJECT_INFORMATION_ACCESS: False, # MUST mark this extension as non-critical ExtensionOID.SUBJECT_KEY_IDENTIFIER: False, # MUST mark this extension as non-critical ExtensionOID.TLS_FEATURE: False, # RFC 7633: MUST NOT be marked critical } ) #: Map of ExtensionOIDs to keys that are usable as class attributes. EXTENSION_KEYS = MappingProxyType( { ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authority_information_access", ExtensionOID.AUTHORITY_KEY_IDENTIFIER: "authority_key_identifier", ExtensionOID.BASIC_CONSTRAINTS: "basic_constraints", ExtensionOID.CERTIFICATE_POLICIES: "certificate_policies", ExtensionOID.CRL_DISTRIBUTION_POINTS: "crl_distribution_points", ExtensionOID.CRL_NUMBER: "crl_number", ExtensionOID.DELTA_CRL_INDICATOR: "delta_crl_indicator", ExtensionOID.EXTENDED_KEY_USAGE: "extended_key_usage", ExtensionOID.FRESHEST_CRL: "freshest_crl", ExtensionOID.INHIBIT_ANY_POLICY: "inhibit_any_policy", ExtensionOID.ISSUER_ALTERNATIVE_NAME: "issuer_alternative_name", ExtensionOID.ISSUING_DISTRIBUTION_POINT: "issuing_distribution_point", ExtensionOID.KEY_USAGE: "key_usage", ExtensionOID.NAME_CONSTRAINTS: "name_constraints", ExtensionOID.OCSP_NO_CHECK: "ocsp_no_check", # RFC 2560 does not really define a spelling ExtensionOID.POLICY_CONSTRAINTS: "policy_constraints", ExtensionOID.POLICY_MAPPINGS: "policy_mappings", ExtensionOID.PRECERT_POISON: "precert_poison", # RFC 7633 ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: "precertificate_signed_certificate_timestamps", # RFC 7633 # NOQA: E501 ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: "signed_certificate_timestamps", # RFC 7633 ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "subject_alternative_name", ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: "subject_directory_attributes", ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subject_information_access", ExtensionOID.SUBJECT_KEY_IDENTIFIER: "subject_key_identifier", ExtensionOID.TLS_FEATURE: "tls_feature", # RFC 7633 } ) #: Map of extension keys to ExtensionOIDs (the inverse of EXTENSION_KEYS). EXTENSION_KEY_OIDS = MappingProxyType({v: k for k, v in EXTENSION_KEYS.items()}) #: Map of ExtensionOIDs to human readable names as they appear in the RFC where they are defined. EXTENSION_NAMES = MappingProxyType( { ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "Authority Information Access", ExtensionOID.AUTHORITY_KEY_IDENTIFIER: "Authority Key Identifier", ExtensionOID.BASIC_CONSTRAINTS: "Basic Constraints", ExtensionOID.CERTIFICATE_POLICIES: "Certificate Policies", ExtensionOID.CRL_DISTRIBUTION_POINTS: "CRL Distribution Points", ExtensionOID.CRL_NUMBER: "CRL Number", ExtensionOID.DELTA_CRL_INDICATOR: "Delta CRL Indicator", ExtensionOID.EXTENDED_KEY_USAGE: "Extended Key Usage", ExtensionOID.FRESHEST_CRL: "Freshest CRL", ExtensionOID.INHIBIT_ANY_POLICY: "Inhibit anyPolicy", ExtensionOID.ISSUER_ALTERNATIVE_NAME: "Issuer Alternative Name", ExtensionOID.ISSUING_DISTRIBUTION_POINT: "Issuing Distribution Point", ExtensionOID.KEY_USAGE: "Key Usage", ExtensionOID.NAME_CONSTRAINTS: "Name Constraints", ExtensionOID.OCSP_NO_CHECK: "OCSP No Check", # RFC 2560 does not really define a spelling ExtensionOID.POLICY_CONSTRAINTS: "Policy Constraints", ExtensionOID.POLICY_MAPPINGS: "Policy Mappings", ExtensionOID.PRECERT_POISON: "Precert Poison", # RFC 7633 ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: "Precertificate Signed Certificate Timestamps", # RFC 7633 # NOQA: E501 ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: "Signed Certificate Timestamps", # RFC 7633 ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "Subject Alternative Name", ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: "Subject Directory Attributes", ExtensionOID.SUBJECT_INFORMATION_ACCESS: "Subject Information Access", ExtensionOID.SUBJECT_KEY_IDENTIFIER: "Subject Key Identifier", ExtensionOID.TLS_FEATURE: "TLS Feature", # RFC 7633 } ) #: Map of ExtensionOIDs to an Integer describing the RFC number where the extension is defined. EXTENSION_RFC_DEFINITION = MappingProxyType( defaultdict( lambda: 5280, { ExtensionOID.OCSP_NO_CHECK: 2560, ExtensionOID.TLS_FEATURE: 7633, ExtensionOID.PRECERT_POISON: 6962, ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: 6962, ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: 6962, }, ) ) #: Map of `kwargs` for :py:class:`~cg:cryptography.x509.KeyUsage` to names in RFC 5280. KEY_USAGE_NAMES = MappingProxyType( { "crl_sign": "cRLSign", "data_encipherment": "dataEncipherment", "decipher_only": "decipherOnly", "digital_signature": "digitalSignature", "encipher_only": "encipherOnly", "key_agreement": "keyAgreement", "key_cert_sign": "keyCertSign", "key_encipherment": "keyEncipherment", "content_commitment": "nonRepudiation", # http://marc.info/?t=107176106300005&r=1&w=2 } ) #: Map of LogEntryTypes to their serialized value. LOG_ENTRY_TYPE_KEYS = MappingProxyType( { LogEntryType.PRE_CERTIFICATE: "precertificate", LogEntryType.X509_CERTIFICATE: "x509_certificate", } ) #: Map of human readable names/serialized values to TLSFeatureTypes. TLS_FEATURE_NAMES = MappingProxyType( { # https://tools.ietf.org/html/rfc6066.html: "OCSPMustStaple": x509.TLSFeatureType.status_request, "status_request": x509.TLSFeatureType.status_request, # https://tools.ietf.org/html/rfc6961.html (not commonly used): "MultipleCertStatusRequest": x509.TLSFeatureType.status_request_v2, "status_request_v2": x509.TLSFeatureType.status_request_v2, } )
[docs]class ReasonFlags(enum.Enum): """An enumeration for CRL reasons. This enumeration is a copy of ``cryptography.x509.ReasonFlags``. We create a copy because any change in the enumeration would trigger a database migration, so up/downgrading cryptography might cause problems with your Django project. """ unspecified = "unspecified" key_compromise = "keyCompromise" ca_compromise = "cACompromise" affiliation_changed = "affiliationChanged" superseded = "superseded" cessation_of_operation = "cessationOfOperation" certificate_hold = "certificateHold" privilege_withdrawn = "privilegeWithdrawn" aa_compromise = "aACompromise" remove_from_crl = "removeFromCRL"
#: Mapping of RFC 5280, section 5.3.1 reason codes too cryptography reason codes REASON_CODES = { 0: ReasonFlags.unspecified, 1: ReasonFlags.key_compromise, 2: ReasonFlags.ca_compromise, 3: ReasonFlags.affiliation_changed, 4: ReasonFlags.superseded, 5: ReasonFlags.cessation_of_operation, 6: ReasonFlags.certificate_hold, 8: ReasonFlags.remove_from_crl, 9: ReasonFlags.privilege_withdrawn, 10: ReasonFlags.aa_compromise, } #: Mapping of ReasonFlags to human-readable strings REVOCATION_REASONS = ( (ReasonFlags.aa_compromise.name, _("Attribute Authority compromised")), (ReasonFlags.affiliation_changed.name, _("Affiliation changed")), (ReasonFlags.ca_compromise.name, _("CA compromised")), (ReasonFlags.certificate_hold.name, _("On Hold")), (ReasonFlags.cessation_of_operation.name, _("Cessation of operation")), (ReasonFlags.key_compromise.name, _("Key compromised")), (ReasonFlags.privilege_withdrawn.name, _("Privilege withdrawn")), (ReasonFlags.remove_from_crl.name, _("Removed from CRL")), (ReasonFlags.superseded.name, _("Superseded")), (ReasonFlags.unspecified.name, _("Unspecified")), )