Skip to content

Commit aa7b39f

Browse files
committed
first draft of smime extension policy
1 parent b849f16 commit aa7b39f

File tree

1 file changed

+55
-2
lines changed
  • src/cryptography/hazmat/primitives/serialization

1 file changed

+55
-2
lines changed

src/cryptography/hazmat/primitives/serialization/pkcs7.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,14 @@
2121
algorithms,
2222
)
2323
from cryptography.utils import _check_byteslike
24-
from cryptography.x509.verification import PolicyBuilder, Store
24+
from cryptography.x509 import Certificate
25+
from cryptography.x509.verification import (
26+
Criticality,
27+
ExtensionPolicy,
28+
Policy,
29+
PolicyBuilder,
30+
Store,
31+
)
2532

2633
load_pem_pkcs7_certificates = rust_pkcs7.load_pem_pkcs7_certificates
2734

@@ -391,8 +398,54 @@ def _smime_signed_decode(data: bytes) -> tuple[bytes | None, bytes]:
391398
raise ValueError("Not an S/MIME signed message")
392399

393400

401+
def get_smime_x509_extension_policies() -> tuple[
402+
ExtensionPolicy, ExtensionPolicy
403+
]:
404+
"""
405+
Gets the default X.509 extension policy for S/MIME. Some specifications
406+
that differ from the standard ones:
407+
- Certificates used as end entities (i.e., the cert used to sign
408+
a PKCS#7/SMIME message) should not have ca=true in their basic
409+
constraints extension.
410+
- EKU_CLIENT_AUTH_OID is not required
411+
- EKU_EMAIL_PROTECTION_OID is required
412+
"""
413+
414+
# CA policy
415+
def _validate_ca(
416+
policy: Policy, cert: Certificate, bc: x509.BasicConstraints
417+
):
418+
assert not bc.ca
419+
420+
ca_policy = ExtensionPolicy.permit_all().require_present(
421+
x509.BasicConstraints,
422+
Criticality.AGNOSTIC,
423+
_validate_ca,
424+
)
425+
426+
# EE policy
427+
def _validate_eku(
428+
policy: Policy, cert: Certificate, eku: x509.ExtendedKeyUsage
429+
):
430+
# Checking for EKU_EMAIL_PROTECTION_OID
431+
assert x509.ExtendedKeyUsageOID.EMAIL_PROTECTION in eku # type: ignore[attr-defined]
432+
433+
ee_policy = ExtensionPolicy.permit_all().require_present(
434+
x509.ExtendedKeyUsage,
435+
Criticality.AGNOSTIC,
436+
_validate_eku,
437+
)
438+
439+
return ca_policy, ee_policy
440+
441+
394442
def _verify_pkcs7_certificates(certificates: list[x509.Certificate]) -> None:
395-
builder = PolicyBuilder().store(Store(certificates))
443+
builder = (
444+
PolicyBuilder()
445+
.store(Store(certificates))
446+
.extension_policies(*get_smime_x509_extension_policies())
447+
)
448+
396449
verifier = builder.build_client_verifier()
397450
verifier.verify(certificates[0], certificates[1:])
398451

0 commit comments

Comments
 (0)