structured-cms 0.10.0

Borrowed CMS SignedData processing with explicit providers and resource accounting
Documentation

structured-cms

CMS SignedData and RFC 3161 timestamp mechanisms over borrowed ASN.1 ranges, explicit resource accounts and injected cryptographic providers. Applications supply content and own trust, policy, acquisition and reporting. The library performs no implicit I/O and includes no cryptographic engine.

The implemented surface covers SignedData rather than encrypted CMS content types. Use the coordinated ASN.1/PKIX/CMS API family:

The snippets below target the coordinated 0.8 API family; see the current registry version.

[dependencies]
structured-asn1 = "0.8"
structured-pkix = "0.8"
structured-cms = "0.8"
  • ContentInfo and SignedData preserve original BER encodings, signer identifiers, certificate/revocation choices and signed attributes. SignerInfo::digest_algorithm() and signature_algorithm() return PKIX AlgorithmReading views: original fields and uniquely bounded malformed parameters remain inspectable with located faults. Only identifier() yields validated provider input. prepare::resolve checks both readings before any provider callback; inspection recovery never grants cryptographic acceptance. Present-empty signed or unsigned attribute sets likewise remain inspectable with EmptyAttributes faults and original ranges. Attributes::read remains strict; read_inspection exposes this uniquely bounded schema violation. Binding and preparation reject it before provider callbacks or payload work. Registered CMS singleton repeats and forbidden signed/unsigned placements retain diagnostics even without a selected certificate. For inspection, Attributes::singleton_inspection_in selects the first byte-identical instance and reports its repeat count under the current producing reader; conflicts refuse. DuplicateAttribute names instance repetition, while AttributeCardinality names value cardinality, including in ESS. Strict binding never becomes a conforming operation through this recovery. SignerInfo::element() preserves original container-local provenance.
  • prepare, verify and provider support explicit raw-message and prehashed verification, full algorithm identities and a shared payload pass. Digests run through the provider's structured_asn1::digest::Digest implementation, and written digest identifiers resolve through structured_pkix::algorithm::digest under the encoding of the message they came from. Provider and input failures remain distinct from invalid or unsupported signatures.
  • ess checks independent signing-certificate attributes; counter walks countersignatures using original parent signature content.
  • attribute_certificate::AttributeCertificate reads the complete v2 structure, retaining Holder/Issuer alternatives, attributes, extensions and the exact original acinfo signature input. SignedData::certificate_choice_reader_in opens CMS's original [2] CHOICE under the current operation budget. This is structural inspection, not RFC5755 profile validation or authorization: the caller checks holder binding, algorithm agreement, signature, AA trust, targeting, validity, critical extensions and revocation before using attributes.
  • attribute_certificate::validation checks the AC's static profile and all RFC5755 §4.3 extension values, preserving audit identity, targeting/proxying obligations and explicit revocation requirements. bind_holder uses an explicitly selected baseCertificateID or entityName and a supplied PKC; bind_authority checks issuer DN/UID and the AA's signature-use/non-CA rules. validation::aa_path::AaPath collects every AAControls restriction below an explicitly selected AA CA, checks path distance and intersects attribute permissions without discarding original attributes. These checks retain original ranges and current/source limits. They do not authenticate paths, verify signatures or object digests, select trust or establish authorization.
  • attribute_certificate::clearance reads current and historical Clearance encodings, preserving default classification, policy-specific bits and opaque security categories. Both registered OIDs are supported without assigning clearance levels or permissions. attribute_certificate::controls::AaControls reads the PKC extension and checks its attribute restrictions and supplied path distance; trust-anchor selection and complete path validation stay with the caller. attribute_certificate::proxy::ProxyInfo checks the authenticated sender, recipient and supplied complete forwarding path against one common proxy set, with unknown group membership and processing errors kept distinct.
  • attribute_certificate::target reads RFC5755 TargetInformation and checks recipient names or caller-supplied group membership. Multiple Targets groups form one union; noncritical extensions and forbidden targetCert alternatives cannot produce a match. Original ranges and current/source work admission are preserved. Unknown membership or opaque name semantics remain unproven; this predicate does not authenticate the AC or authorize attribute use.
  • attribute_certificate::ietf::IetfAttrSyntax decodes group and chargingIdentity assertions with their original policyAuthority and homogeneous borrowed octet, OID or UTF-8 values. Registered-attribute reads enforce outer singleton cardinality; an empty inner sequence stays empty. Short current queries retain original source/depth and independently owned metadata accounting. Decoding does not establish membership, authority trust or charging permission.
  • attribute_certificate::role::RoleSyntax decodes the original role URI and optional roleAuthority names. Registered id-at-role reads check every value and preserve multiple assertions in source order, with DER and source/current resource admission. Authority trust, role allocation and permissions remain application decisions; decoding never dereferences the URI.
  • attribute_certificate::service::SvceAuthInfo decodes service/holder names and optional borrowed authentication bytes. Registered authenticationInfo and accessIdentity reads preserve every original value; accessIdentity rejects authInfo even when empty. Source/current resource admission and DER apply, while authentication and authorization remain with the application. Debug formatting shows source ranges only, without credential contents.
  • timestamp::Request reads original TimeStampReq. timestamp::Token separates readable inspection from complete signature, ESS, TSA, imprint, request and time checking. The caller supplies UTC information and request windows.
  • archive reads the CAdES ats-hash-index-v3 of an archive-time-stamp-v3 (ETSI EN 319 122-1 §5.5). check_index matches every index entry against the root SignedData certificate and revocation choices and the signer's unsigned attribute values, hashed over their original encodings; an entry without its element invalidates the index, an element without an entry is reported as unprotected. imprint_input yields the §5.5.3 ranges the token's imprint is checked over, and same_algorithm the required index/imprint agreement.
  • cades::profile_faults reports where a SignerInfo uses the freedom of the generic CMS and ESS schemas against the CAdES profile (EN 319 122-1 §§5.2-5.5): an attribute in the wrong set, a single-valued attribute with another value count, a repeated ESS content attribute (RFC 2634 §1.3.4), content-hints or mime-type inside a countersignature, an ats-hash-index-v3 outside an archive time-stamp token's signer, ESS policies and an implied signature policy. Level requirements and verdicts stay with the application.

Borrowed views keep original document ranges. Independently retained results use accounted storage that remains charged until its capacity is freed. Fallible copies reserve additional storage; moving a result does not copy it. Producing reader operations enforce both local and aggregate work ceilings. Lazy queries preserve original provenance and fund work through the current operation.

Constructed content can have several physical ranges. SourceMap retains that mapping independently of temporary joins. Nested timestamp checking preserves separate CMS-envelope and TSTInfo coordinate contexts. A foreign-reader refusal occurs before map admission; it is caller misuse, not malformed document data. Timestamp inspection preserves a uniquely readable TSTInfo followed by trailing carried bytes, with a located TrailingData fault and the original source map. Fault retention is fallible and uses the producing execution's resource limits.

timestamp::Evidence records successful common checks, not a trust decision. Applications must validate the TSA certification path and status, enforce signed ESS path restrictions and apply their algorithm/security policy. Malformed inspection faults do not produce evidence. Content discovery, replay history, networking, clocks and product timelines remain outside this crate.

The repository's scripts/qualify-cades-corpus.py checks SHA256-pinned public DSS CAdES fixtures with an independent DER walker: a conforming archive time-stamp whose imprint is recomputed, indexes naming a certificate or revocation the signature does not hold, and a TS 101 733 index that is not read as v3. The archive results must agree with it entry by entry. Upstream payloads and their licence notice remain outside packages in target/.

The runtime supports no_std + alloc; std is optional. Cryptographic test adapters are development-only oracles, not qualified production providers or proof of their internal resource accounting.