Skip to content

Commit a6d5311

Browse files
authored
CryptoOps::PolicyExtra to allow passing user data inside a Policy. (#12387)
1 parent 116c5af commit a6d5311

File tree

5 files changed

+64
-34
lines changed

5 files changed

+64
-34
lines changed

src/rust/cryptography-x509-verification/src/certificate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Xw4nMqk=
5555
type Key = ();
5656
type Err = ();
5757
type CertificateExtra = ();
58+
type PolicyExtra = ();
5859

5960
fn public_key(&self, _cert: &Certificate<'_>) -> Result<Self::Key, Self::Err> {
6061
// Simulate failing to retrieve a public key.

src/rust/cryptography-x509-verification/src/ops.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ pub trait CryptoOps {
7272
/// Extra data that's passed around with the certificate.
7373
type CertificateExtra;
7474

75+
/// Extra data that's accessible alongside the PolicyDefinition.
76+
type PolicyExtra;
77+
7578
/// Extracts the public key from the given `Certificate` in
7679
/// a `Key` format known by the cryptographic backend, or `None`
7780
/// if the key is malformed.

src/rust/cryptography-x509-verification/src/policy/extension.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ mod tests {
552552
use crate::certificate::tests::PublicKeyErrorOps;
553553
use crate::ops::tests::{cert, v1_cert_pem};
554554
use crate::ops::CryptoOps;
555-
use crate::policy::{Policy, Subject, ValidationResult};
555+
use crate::policy::{Policy, PolicyDefinition, Subject, ValidationResult};
556556
use crate::types::DNSName;
557557

558558
#[test]
@@ -602,12 +602,13 @@ mod tests {
602602
let cert_pem = v1_cert_pem();
603603
let cert = cert(&cert_pem);
604604
let ops = PublicKeyErrorOps {};
605-
let policy = Policy::server(
605+
let policy_def = PolicyDefinition::server(
606606
ops,
607607
Subject::DNS(DNSName::new("example.com").unwrap()),
608608
epoch(),
609609
None,
610610
);
611+
let policy = Policy::new(&policy_def, ());
611612

612613
// Test a policy that stipulates that a given extension MUST be present.
613614
let extension_validator =
@@ -642,12 +643,13 @@ mod tests {
642643
let cert_pem = v1_cert_pem();
643644
let cert = cert(&cert_pem);
644645
let ops = PublicKeyErrorOps {};
645-
let policy = Policy::server(
646+
let policy_def = PolicyDefinition::server(
646647
ops,
647648
Subject::DNS(DNSName::new("example.com").unwrap()),
648649
epoch(),
649650
None,
650651
);
652+
let policy = Policy::new(&policy_def, ());
651653

652654
// Test a validator that stipulates that a given extension CAN be present.
653655
let extension_validator = ExtensionValidator::maybe_present(
@@ -676,12 +678,13 @@ mod tests {
676678
let cert_pem = v1_cert_pem();
677679
let cert = cert(&cert_pem);
678680
let ops = PublicKeyErrorOps {};
679-
let policy = Policy::server(
681+
let policy_def = PolicyDefinition::server(
680682
ops,
681683
Subject::DNS(DNSName::new("example.com").unwrap()),
682684
epoch(),
683685
None,
684686
);
687+
let policy = Policy::new(&policy_def, ());
685688

686689
// Test a validator that stipulates that a given extension MUST NOT be present.
687690
let extension_validator = ExtensionValidator::not_present();
@@ -707,12 +710,13 @@ mod tests {
707710
let cert_pem = v1_cert_pem();
708711
let cert = cert(&cert_pem);
709712
let ops = PublicKeyErrorOps {};
710-
let policy = Policy::server(
713+
let policy_def = PolicyDefinition::server(
711714
ops,
712715
Subject::DNS(DNSName::new("example.com").unwrap()),
713716
epoch(),
714717
None,
715718
);
719+
let policy = Policy::new(&policy_def, ());
716720

717721
// Test a present policy that stipulates that a given extension MUST be critical.
718722
let extension_validator =
@@ -736,12 +740,13 @@ mod tests {
736740
let cert_pem = v1_cert_pem();
737741
let cert = cert(&cert_pem);
738742
let ops = PublicKeyErrorOps {};
739-
let policy = Policy::server(
743+
let policy_def = PolicyDefinition::server(
740744
ops,
741745
Subject::DNS(DNSName::new("example.com").unwrap()),
742746
epoch(),
743747
None,
744748
);
749+
let policy = Policy::new(&policy_def, ());
745750

746751
// Test a maybe present validator that stipulates that a given extension MUST be critical.
747752
let extension_validator = ExtensionValidator::maybe_present(

src/rust/cryptography-x509-verification/src/policy/mod.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
mod extension;
66

77
use std::collections::HashSet;
8-
use std::ops::Range;
8+
use std::ops::{Deref, Range};
99
use std::sync::Arc;
1010

1111
use asn1::ObjectIdentifier;
@@ -196,8 +196,8 @@ impl Subject<'_> {
196196
}
197197
}
198198

199-
/// A `Policy` describes user-configurable aspects of X.509 path validation.
200-
pub struct Policy<'a, B: CryptoOps> {
199+
/// A `PolicyDefinition` describes user-configurable aspects of X.509 path validation.
200+
pub struct PolicyDefinition<'a, B: CryptoOps> {
201201
pub ops: B,
202202

203203
/// A top-level constraint on the length of intermediate CA paths
@@ -234,7 +234,7 @@ pub struct Policy<'a, B: CryptoOps> {
234234
ee_extension_policy: ExtensionPolicy<B>,
235235
}
236236

237-
impl<'a, B: CryptoOps> Policy<'a, B> {
237+
impl<'a, B: CryptoOps> PolicyDefinition<'a, B> {
238238
fn new(
239239
ops: B,
240240
subject: Option<Subject<'a>>,
@@ -372,6 +372,25 @@ impl<'a, B: CryptoOps> Policy<'a, B> {
372372
EKU_SERVER_AUTH_OID.clone(),
373373
)
374374
}
375+
}
376+
377+
pub struct Policy<'a, B: CryptoOps> {
378+
definition: &'a PolicyDefinition<'a, B>,
379+
pub extra: B::PolicyExtra,
380+
}
381+
382+
impl<'a, B: CryptoOps> Deref for Policy<'a, B> {
383+
type Target = PolicyDefinition<'a, B>;
384+
385+
fn deref(&self) -> &Self::Target {
386+
self.definition
387+
}
388+
}
389+
390+
impl<'a, B: CryptoOps> Policy<'a, B> {
391+
pub fn new(definition: &'a PolicyDefinition<'a, B>, extra: B::PolicyExtra) -> Self {
392+
Self { definition, extra }
393+
}
375394

376395
fn permits_basic<'chain>(&self, cert: &Certificate<'_>) -> ValidationResult<'chain, (), B> {
377396
// CA/B 7.1.1:

src/rust/src/x509/verify.rs

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use cryptography_x509::certificate::Certificate;
66
use cryptography_x509::extensions::SubjectAlternativeName;
77
use cryptography_x509::oid::SUBJECT_ALTERNATIVE_NAME_OID;
88
use cryptography_x509_verification::ops::{CryptoOps, VerificationCertificate};
9-
use cryptography_x509_verification::policy::{Policy, Subject};
9+
use cryptography_x509_verification::policy::{Policy, PolicyDefinition, Subject};
1010
use cryptography_x509_verification::trust_store::Store;
1111
use cryptography_x509_verification::types::{DNSName, IPAddress};
1212
use pyo3::types::{PyAnyMethods, PyListMethods};
@@ -25,6 +25,7 @@ impl CryptoOps for PyCryptoOps {
2525
type Key = pyo3::Py<pyo3::PyAny>;
2626
type Err = CryptographyError;
2727
type CertificateExtra = pyo3::Py<PyCertificate>;
28+
type PolicyExtra = ();
2829

2930
fn public_key(&self, cert: &Certificate<'_>) -> Result<Self::Key, Self::Err> {
3031
pyo3::Python::with_gil(|py| -> Result<Self::Key, Self::Err> {
@@ -158,9 +159,10 @@ impl PolicyBuilder {
158159
};
159160

160161
// TODO: Pass extension policies here once implemented in cryptography-x509-verification.
161-
let policy = Policy::client(PyCryptoOps {}, time, self.max_chain_depth);
162-
163-
Ok(PyClientVerifier { policy, store })
162+
Ok(PyClientVerifier {
163+
policy_definition: PolicyDefinition::client(PyCryptoOps {}, time, self.max_chain_depth),
164+
store,
165+
})
164166
}
165167

166168
fn build_server_verifier(
@@ -185,11 +187,11 @@ impl PolicyBuilder {
185187
};
186188
let subject_owner = build_subject_owner(py, &subject)?;
187189

188-
let policy = OwnedPolicy::try_new(subject_owner, |subject_owner| {
190+
let policy_definition = OwnedPolicyDefinition::try_new(subject_owner, |subject_owner| {
189191
let subject = build_subject(py, subject_owner)?;
190192

191193
// TODO: Pass extension policies here once implemented in cryptography-x509-verification.
192-
Ok::<PyCryptoPolicy<'_>, pyo3::PyErr>(Policy::server(
194+
Ok::<PyCryptoPolicyDefinition<'_>, pyo3::PyErr>(PolicyDefinition::server(
193195
PyCryptoOps {},
194196
subject,
195197
time,
@@ -199,13 +201,13 @@ impl PolicyBuilder {
199201

200202
Ok(PyServerVerifier {
201203
py_subject: subject,
202-
policy,
204+
policy_definition,
203205
store,
204206
})
205207
}
206208
}
207209

208-
type PyCryptoPolicy<'a> = Policy<'a, PyCryptoOps>;
210+
type PyCryptoPolicyDefinition<'a> = PolicyDefinition<'a, PyCryptoOps>;
209211

210212
/// This enum exists solely to provide heterogeneously typed ownership for `OwnedPolicy`.
211213
enum SubjectOwner {
@@ -219,11 +221,11 @@ enum SubjectOwner {
219221
}
220222

221223
self_cell::self_cell!(
222-
struct OwnedPolicy {
224+
struct OwnedPolicyDefinition {
223225
owner: SubjectOwner,
224226

225227
#[covariant]
226-
dependent: PyCryptoPolicy,
228+
dependent: PyCryptoPolicyDefinition,
227229
}
228230
);
229231

@@ -245,14 +247,14 @@ pub(crate) struct PyVerifiedClient {
245247
module = "cryptography.hazmat.bindings._rust.x509"
246248
)]
247249
pub(crate) struct PyClientVerifier {
248-
policy: PyCryptoPolicy<'static>,
250+
policy_definition: PyCryptoPolicyDefinition<'static>,
249251
#[pyo3(get)]
250252
store: pyo3::Py<PyStore>,
251253
}
252254

253255
impl PyClientVerifier {
254-
fn as_policy(&self) -> &Policy<'_, PyCryptoOps> {
255-
&self.policy
256+
fn as_policy_def(&self) -> &PyCryptoPolicyDefinition<'_> {
257+
&self.policy_definition
256258
}
257259
}
258260

@@ -263,12 +265,12 @@ impl PyClientVerifier {
263265
&self,
264266
py: pyo3::Python<'p>,
265267
) -> pyo3::PyResult<pyo3::Bound<'p, pyo3::PyAny>> {
266-
datetime_to_py(py, &self.as_policy().validation_time)
268+
datetime_to_py(py, &self.as_policy_def().validation_time)
267269
}
268270

269271
#[getter]
270272
fn max_chain_depth(&self) -> u8 {
271-
self.as_policy().max_chain_depth
273+
self.as_policy_def().max_chain_depth
272274
}
273275

274276
fn verify(
@@ -277,7 +279,7 @@ impl PyClientVerifier {
277279
leaf: pyo3::Py<PyCertificate>,
278280
intermediates: Vec<pyo3::Py<PyCertificate>>,
279281
) -> CryptographyResult<PyVerifiedClient> {
280-
let policy = self.as_policy();
282+
let policy = Policy::new(self.as_policy_def(), ());
281283
let store = self.store.get();
282284

283285
let intermediates = intermediates
@@ -290,7 +292,7 @@ impl PyClientVerifier {
290292
let chain = cryptography_x509_verification::verify(
291293
&v,
292294
&intermediates,
293-
policy,
295+
&policy,
294296
store.raw.borrow_dependent(),
295297
)
296298
.or_else(|e| handle_validation_error(py, e))?;
@@ -329,14 +331,14 @@ impl PyClientVerifier {
329331
pub(crate) struct PyServerVerifier {
330332
#[pyo3(get, name = "subject")]
331333
py_subject: pyo3::Py<pyo3::PyAny>,
332-
policy: OwnedPolicy,
334+
policy_definition: OwnedPolicyDefinition,
333335
#[pyo3(get)]
334336
store: pyo3::Py<PyStore>,
335337
}
336338

337339
impl PyServerVerifier {
338-
fn as_policy(&self) -> &Policy<'_, PyCryptoOps> {
339-
self.policy.borrow_dependent()
340+
fn as_policy_def(&self) -> &PyCryptoPolicyDefinition<'_> {
341+
self.policy_definition.borrow_dependent()
340342
}
341343
}
342344

@@ -347,12 +349,12 @@ impl PyServerVerifier {
347349
&self,
348350
py: pyo3::Python<'p>,
349351
) -> pyo3::PyResult<pyo3::Bound<'p, pyo3::PyAny>> {
350-
datetime_to_py(py, &self.as_policy().validation_time)
352+
datetime_to_py(py, &self.as_policy_def().validation_time)
351353
}
352354

353355
#[getter]
354356
fn max_chain_depth(&self) -> u8 {
355-
self.as_policy().max_chain_depth
357+
self.as_policy_def().max_chain_depth
356358
}
357359

358360
fn verify<'p>(
@@ -361,7 +363,7 @@ impl PyServerVerifier {
361363
leaf: pyo3::Py<PyCertificate>,
362364
intermediates: Vec<pyo3::Py<PyCertificate>>,
363365
) -> CryptographyResult<pyo3::Bound<'p, pyo3::types::PyList>> {
364-
let policy = self.as_policy();
366+
let policy = Policy::new(self.as_policy_def(), ());
365367
let store = self.store.get();
366368

367369
let intermediates = intermediates
@@ -374,7 +376,7 @@ impl PyServerVerifier {
374376
let chain = cryptography_x509_verification::verify(
375377
&v,
376378
&intermediates,
377-
policy,
379+
&policy,
378380
store.raw.borrow_dependent(),
379381
)
380382
.or_else(|e| handle_validation_error(py, e))?;

0 commit comments

Comments
 (0)