|
21 | 21 | algorithms,
|
22 | 22 | )
|
23 | 23 | 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 | +) |
25 | 32 |
|
26 | 33 | load_pem_pkcs7_certificates = rust_pkcs7.load_pem_pkcs7_certificates
|
27 | 34 |
|
@@ -391,8 +398,54 @@ def _smime_signed_decode(data: bytes) -> tuple[bytes | None, bytes]:
|
391 | 398 | raise ValueError("Not an S/MIME signed message")
|
392 | 399 |
|
393 | 400 |
|
| 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 | + |
394 | 442 | 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 | + |
396 | 449 | verifier = builder.build_client_verifier()
|
397 | 450 | verifier.verify(certificates[0], certificates[1:])
|
398 | 451 |
|
|
0 commit comments