Skip to content

x509 Verification: Python support for custom ext. policies. #12418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/cryptography/hazmat/bindings/_rust/x509.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ class PolicyBuilder:
def time(self, new_time: datetime.datetime) -> PolicyBuilder: ...
def store(self, new_store: Store) -> PolicyBuilder: ...
def max_chain_depth(self, new_max_chain_depth: int) -> PolicyBuilder: ...
def extension_policies(
self, new_ca_policy: ExtensionPolicy, new_ee_policy: ExtensionPolicy
) -> PolicyBuilder: ...
def build_client_verifier(self) -> ClientVerifier: ...
def build_server_verifier(
self, subject: x509.verification.Subject
Expand All @@ -218,6 +221,50 @@ class Policy:
@property
def minimum_rsa_modulus(self) -> int: ...

class Criticality:
CRITICAL: Criticality
AGNOSTIC: Criticality
NON_CRITICAL: Criticality

type MaybeExtensionValidatorCallback[T: x509.ExtensionType] = typing.Callable[
[
Policy,
x509.Certificate,
T | None,
],
None,
]

type PresentExtensionValidatorCallback[T: x509.ExtensionType] = (
typing.Callable[
[Policy, x509.Certificate, T],
None,
]
)

class ExtensionPolicy:
@staticmethod
def permit_all() -> ExtensionPolicy: ...
@staticmethod
def webpki_defaults_ca() -> ExtensionPolicy: ...
@staticmethod
def webpki_defaults_ee() -> ExtensionPolicy: ...
def require_not_present(
self, extension_type: type[x509.ExtensionType]
) -> ExtensionPolicy: ...
def may_be_present[T: x509.ExtensionType](
self,
extension_type: type[T],
criticality: Criticality,
validator: MaybeExtensionValidatorCallback[T] | None,
) -> ExtensionPolicy: ...
def require_present[T: x509.ExtensionType](
self,
extension_type: type[T],
criticality: Criticality,
validator: PresentExtensionValidatorCallback[T] | None,
) -> ExtensionPolicy: ...

class VerifiedClient:
@property
def subjects(self) -> list[x509.GeneralName] | None: ...
Expand Down
5 changes: 5 additions & 0 deletions src/cryptography/x509/verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

__all__ = [
"ClientVerifier",
"Criticality",
"ExtensionPolicy",
"Policy",
"PolicyBuilder",
"ServerVerifier",
"Store",
Expand All @@ -26,4 +29,6 @@
ServerVerifier = rust_x509.ServerVerifier
PolicyBuilder = rust_x509.PolicyBuilder
Policy = rust_x509.Policy
ExtensionPolicy = rust_x509.ExtensionPolicy
Criticality = rust_x509.Criticality
VerificationError = rust_x509.VerificationError
2 changes: 1 addition & 1 deletion src/rust/cryptography-x509-verification/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub struct ValidationError<'chain, B: CryptoOps> {
}

impl<'chain, B: CryptoOps> ValidationError<'chain, B> {
pub(crate) fn new(kind: ValidationErrorKind<'chain, B>) -> Self {
pub fn new(kind: ValidationErrorKind<'chain, B>) -> Self {
ValidationError { kind, cert: None }
}

Expand Down
24 changes: 24 additions & 0 deletions src/rust/cryptography-x509-verification/src/policy/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::{
ops::CryptoOps, policy::Policy, ValidationError, ValidationErrorKind, ValidationResult,
};

#[derive(Clone)]
pub struct ExtensionPolicy<'cb, B: CryptoOps> {
pub authority_information_access: ExtensionValidator<'cb, B>,
pub authority_key_identifier: ExtensionValidator<'cb, B>,
Expand All @@ -28,6 +29,27 @@ pub struct ExtensionPolicy<'cb, B: CryptoOps> {
}

impl<'cb, B: CryptoOps + 'cb> ExtensionPolicy<'cb, B> {
pub fn new_permit_all() -> Self {
const fn make_permissive_validator<'cb, B: CryptoOps + 'cb>() -> ExtensionValidator<'cb, B>
{
ExtensionValidator::MaybePresent {
criticality: Criticality::Agnostic,
validator: None,
}
}

ExtensionPolicy {
authority_information_access: make_permissive_validator(),
authority_key_identifier: make_permissive_validator(),
subject_key_identifier: make_permissive_validator(),
key_usage: make_permissive_validator(),
subject_alternative_name: make_permissive_validator(),
basic_constraints: make_permissive_validator(),
name_constraints: make_permissive_validator(),
extended_key_usage: make_permissive_validator(),
}
}

pub fn new_default_webpki_ca() -> Self {
ExtensionPolicy {
// 5280 4.2.2.1: Authority Information Access
Expand Down Expand Up @@ -214,6 +236,7 @@ impl<'cb, B: CryptoOps + 'cb> ExtensionPolicy<'cb, B> {
}

/// Represents different criticality states for an extension.
#[derive(Clone)]
pub enum Criticality {
/// The extension MUST be marked as critical.
Critical,
Expand Down Expand Up @@ -258,6 +281,7 @@ pub type MaybeExtensionValidatorCallback<'cb, B> = Arc<
>;

/// Represents different validation states for an extension.
#[derive(Clone)]
pub enum ExtensionValidator<'cb, B: CryptoOps> {
/// The extension MUST NOT be present.
NotPresent,
Expand Down
4 changes: 2 additions & 2 deletions src/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ mod _rust {
use crate::x509::sct::Sct;
#[pymodule_export]
use crate::x509::verify::{
PolicyBuilder, PyClientVerifier, PyPolicy, PyServerVerifier, PyStore, PyVerifiedClient,
VerificationError,
PolicyBuilder, PyClientVerifier, PyCriticality, PyExtensionPolicy, PyPolicy,
PyServerVerifier, PyStore, PyVerifiedClient, VerificationError,
};
}

Expand Down
3 changes: 3 additions & 0 deletions src/rust/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ pub static REASON_FLAGS: LazyPyImport = LazyPyImport::new("cryptography.x509", &
pub static ATTRIBUTE: LazyPyImport = LazyPyImport::new("cryptography.x509", &["Attribute"]);
pub static ATTRIBUTES: LazyPyImport = LazyPyImport::new("cryptography.x509", &["Attributes"]);

pub static EXTENSION_TYPE: LazyPyImport =
LazyPyImport::new("cryptography.x509", &["ExtensionType"]);

pub static CRL_NUMBER: LazyPyImport = LazyPyImport::new("cryptography.x509", &["CRLNumber"]);
pub static DELTA_CRL_INDICATOR: LazyPyImport =
LazyPyImport::new("cryptography.x509", &["DeltaCRLIndicator"]);
Expand Down
Loading
Loading