1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! Pluggable configuration trait surface for quote verification.
//!
//! Quote verification depends on a small set of operations on certificates,
//! signatures, and crypto primitives. Each is captured by a small trait so a
//! downstream consumer (e.g. a smart contract building for WASM) can supply a
//! smaller-footprint implementation without forking this crate. The audited
//! in-tree implementations live in [`crate::x509`], [`crate::signature`], and
//! [`crate::crypto`]; the bundles in [`crate::configs`] (incl.
//! [`DefaultConfig`](crate::configs::DefaultConfig)) pair them into ready-to-use
//! [`Config`]s.
//!
//! ## Config trait
//!
//! [`Config`] bundles the pluggable components as associated types so they can
//! be swapped independently — e.g. keep the audited cert parser but bring your
//! own micro-encoder. A custom config is just a marker type implementing
//! [`Config`]:
//!
//! ```ignore
//! struct MyConfig;
//! impl dcap_qvl::config::Config for MyConfig {
//! type X509 = dcap_qvl::x509::X509CertBackend; // keep audited
//! type SigEncoder = MyMicroEncoder; // custom
//! type Crypto = dcap_qvl::crypto::RingCrypto;
//! }
//!
//! dcap_qvl::verify::verify_with::<MyConfig>(quote, &collateral, now)?;
//! ```
//!
//! ## Auditing
//!
//! Only the in-tree backends ([`crate::x509::X509CertBackend`],
//! [`crate::signature::DerSigEncoder`], [`crate::crypto::RingCrypto`] /
//! [`crate::crypto::RustCryptoCrypto`]) and the bundles in [`crate::configs`]
//! are audited as part of `dcap-qvl`. Custom implementations of [`X509Codec`]
//! / [`ParsedCert`] / [`EcdsaSigEncoder`] / [`CryptoProvider`] are the
//! implementer's responsibility; they SHOULD be checked for byte-for-byte
//! equivalence against [`DefaultConfig`](crate::configs::DefaultConfig) on a
//! representative corpus (see `tests/config_conformance.rs`).
//!
//! ## Trait shape
//!
//! Sub-trait methods (other than [`X509Codec::from_der`]) are associated
//! functions, not `&self` methods, so backends are expected to be zero-sized
//! marker types. [`X509Codec`] is the exception: it produces a [`ParsedCert`]
//! that owns or borrows the parsed data, so multiple field accesses share a
//! single parse.
use String;
use Vec;
use Result;
/// X.509 certificate parser factory.
///
/// Implementations MUST conform to RFC 5280 and X.690 (DER). A backend
/// parses a certificate once via [`X509Codec::from_der`], returning a
/// [`ParsedCert`] that exposes the fields needed by quote verification as
/// `&self` accessors — so a caller that touches multiple fields of the same
/// certificate pays the parsing cost only once.
///
/// The associated type [`X509Codec::Parsed`] is generic over the input
/// lifetime, allowing implementations to choose whether to own their parsed
/// representation or borrow zero-copy from the input DER bytes.
/// Read-only accessors over a parsed X.509 certificate.
/// DER encoding of ECDSA signatures.
///
/// DCAP quotes carry signatures as raw `r ‖ s` byte strings, but webpki's
/// signature verifier expects them encoded as `Ecdsa-Sig-Value` (RFC 5480):
/// `SEQUENCE { r INTEGER, s INTEGER }`. This trait performs that conversion.
/// Cryptographic primitives required by quote verification: the ECDSA
/// signature verification algorithm passed to webpki, plus a SHA-256 hash.
///
/// Implementations are typically zero-sized marker types whose methods are
/// associated functions delegating to a chosen crypto crate (ring, RustCrypto,
/// hardware accelerator, etc.).
/// Configuration bundle selecting an implementation for each pluggable
/// component.
///
/// Implementations are typically zero-sized marker types. Adding a new
/// pluggable component in the future means adding a new associated type here,
/// which is backwards-compatible (existing custom configs continue to work as
/// long as they implement the new associated type — defaulted with a `where`
/// clause if needed).