Skip to main content

structured_pkix/
revocation.rs

1//! Original borrowed status targets shared by CRL and OCSP processing.
2
3use crate::{Certificate, Extensions, Name, Version};
4use structured_asn1::memory::{Execution, Work};
5use structured_asn1::{Integer, Parser, Span};
6
7/// Original certificate category, not a deployment policy.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum TargetKind {
10    /// A public-key certificate with its actual schema version.
11    PublicKey(Version),
12    /// An RFC5755 attribute certificate, without an invented public key or cA bit.
13    Attribute,
14}
15
16/// Written revocation scheme, independently of successful status evidence.
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum RevocationScheme {
19    /// Status sources may be processed; absent pointers are not an exemption.
20    Available,
21    /// RFC5755 ยง6 `NoRevAvail`, never CRL absence or positive OCSP evidence.
22    NoRevAvail,
23}
24
25/// Coherently associated original fields for the common status processors.
26///
27/// Implementations are trusted O(1) adapters: borrow original fields without
28/// parsing, allocation or normalization. Every field describes the same target.
29/// This does not authenticate it or its issuer. Deferred work retains the source
30/// ceiling and the current operation. The issuer/responder remains a real PKC;
31/// an AC does not acquire an artificial subject public key.
32///
33/// ```
34/// use structured_asn1::memory::Work;
35/// use structured_pkix::{Result, revocation::RevocationTarget,
36///     crl::{Authenticated, ScopeOutcome}};
37/// fn applicable<'a>(source: &Authenticated<'_, '_>, target: &impl RevocationTarget<'a>,
38///     work: &impl Work) -> Result<bool> {
39///     Ok(matches!(source.scope(target, work)?, ScopeOutcome::Applicable(_)))
40/// }
41/// ```
42pub trait RevocationTarget<'a> {
43    /// Original issuer DN.
44    fn issuer(&self) -> &Name<'a>;
45    /// Original arbitrary-width serial.
46    fn serial(&self) -> Integer<'a>;
47    /// Original extension catalogue, absent where the schema omitted it.
48    fn extensions(&self) -> Option<&Extensions<'a>>;
49    /// Actual schema category.
50    fn kind(&self) -> TargetKind;
51    /// Written scheme, never inferred from short validity or absent URLs.
52    fn revocation_scheme(&self) -> RevocationScheme;
53    /// Whole original encoding used to bind evidence contributors.
54    fn encoded(&self) -> &'a [u8];
55    /// Honest source enclosure for processing failures.
56    fn span(&self) -> Span;
57    /// Original parser for these fields, including deferred BER depth and limits.
58    fn source_parser(&self) -> &'a Parser;
59    /// Borrow the original source ceiling and current operation.
60    fn execution_in<'op, W: Work>(&'op self, work: &'op W) -> Execution<'op>
61    where
62        'a: 'op,
63    {
64        work.execution_for(self.source_parser())
65    }
66}
67
68impl<'a> RevocationTarget<'a> for Certificate<'a> {
69    fn source_parser(&self) -> &'a Parser {
70        self.tbs().signature().source_parser()
71    }
72    fn issuer(&self) -> &Name<'a> {
73        self.tbs().issuer()
74    }
75    fn serial(&self) -> Integer<'a> {
76        self.tbs().serial()
77    }
78    fn extensions(&self) -> Option<&Extensions<'a>> {
79        Some(self.tbs().extensions())
80    }
81    fn kind(&self) -> TargetKind {
82        TargetKind::PublicKey(self.tbs().version())
83    }
84    fn revocation_scheme(&self) -> RevocationScheme {
85        RevocationScheme::Available
86    }
87    fn encoded(&self) -> &'a [u8] {
88        self.as_bytes()
89    }
90    fn span(&self) -> Span {
91        Certificate::span(self)
92    }
93}