Skip to content

Unable to parse client certificates with critical 2.5.29.32 CertificatePolicies extension #14850

@DragoonAethis

Description

@DragoonAethis

I'm trying to verify a XAdES-signed XML document using signxml, currently being upgraded from version 3.x to 4.x, which involves switching the certificate parser from pyopenssl to pyca/cryptography, and I'm hitting a wall.

The client certificate embedded in the XAdES signature contains a critical OID 2.5.29.32 CertificatePolicies extension. Trying to parse it normally raises an x509.verification.VerificationError error: validation failed: candidates exhausted: invalid extension: 2.5.29.32: certificate contains unaccounted-for critical extensions

I thought the solution is to amend the PolicyBuilder with something like this:

from cryptography.x509.extensions import SubjectAlternativeName, CertificatePolicies, BasicConstraints
from cryptography.x509.verification import PolicyBuilder, ExtensionPolicy, Criticality

ca_policy = (ExtensionPolicy.webpki_defaults_ca()
             .may_be_present(SubjectAlternativeName, Criticality.AGNOSTIC, None)  # MS KRK certs don't have SAN extensions
             .may_be_present(CertificatePolicies, Criticality.AGNOSTIC, None)  # <- This is the problem :(
)
ee_policy = (ExtensionPolicy.webpki_defaults_ee()
             .may_be_present(SubjectAlternativeName, Criticality.AGNOSTIC, None)
             .may_be_present(CertificatePolicies, Criticality.AGNOSTIC, None)
)

builder = (
    PolicyBuilder()
        .extension_policies(ca_policy=ca_policy, ee_policy=ee_policy)
        .store(self.store)
        .time(self.verification_time or datetime.now()
)

The builder only ever creates a client verifier, not the server verifier. Trying to configure the policy like this raises an exception when setting may_be_present(CertificatePolicies, ...): ValueError: Unsupported extension OID: 2.5.29.32

I tried to work around the thing with just:

ca_policy = ExtensionPolicy.permit_all().require_present(BasicConstraints, Criticality.CRITICAL, None)
ee_policy = ExtensionPolicy.permit_all()

But it still fails on certificate contains unaccounted-for critical extensions as it seems like the validator has a hardcoded list of extensions that may be critical.

Is it possible to make it parse the certificate regardless of that?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions