1pub mod cacerts;
24pub mod content_type;
25pub mod csrattrs;
26pub mod enroll;
27pub mod fullcmc;
28pub mod reenroll;
29pub mod serverkeygen;
30
31use thiserror::Error;
32
33#[derive(Debug, Error, Clone)]
35pub enum EstError {
36 #[error("Invalid base64 encoding: {0}")]
38 InvalidBase64(String),
39
40 #[error("Invalid DER encoding: {0}")]
42 InvalidDer(String),
43
44 #[error("Invalid PKCS#7 structure: {0}")]
46 InvalidPkcs7(String),
47
48 #[error("Invalid PKCS#10 CSR: {0}")]
50 InvalidPkcs10(String),
51
52 #[error("Invalid PKCS#8 private key: {0}")]
54 InvalidPkcs8(String),
55
56 #[error("Invalid CMC request: {0}")]
58 InvalidCmc(String),
59
60 #[error("Missing required field: {0}")]
62 MissingField(String),
63
64 #[error("Unsupported algorithm: OID {0}")]
66 UnsupportedAlgorithm(String),
67
68 #[error("Invalid multipart MIME: {0}")]
70 InvalidMultipart(String),
71
72 #[error("Subject mismatch: expected {expected}, got {actual}")]
74 SubjectMismatch { expected: String, actual: String },
75
76 #[error("Invalid proof of possession: {0}")]
78 InvalidPop(String),
79
80 #[error("Invalid EKU: expected id-kp-cmcRA")]
82 InvalidEku,
83
84 #[error("ML-KEM level mismatch: requested {requested}, server only supports {supported}")]
86 MlKemLevelMismatch { requested: u16, supported: u16 },
87
88 #[error("EST protocol error: {0}")]
90 Protocol(String),
91}
92
93pub type EstResult<T> = Result<T, EstError>;
95
96#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
98pub enum EstOperation {
99 CaCerts,
101
102 SimpleEnroll,
104
105 SimpleReenroll,
107
108 FullCmc,
110
111 ServerKeygen,
113
114 CsrAttrs,
116}
117
118impl EstOperation {
119 pub fn path(&self) -> &'static str {
121 match self {
122 Self::CaCerts => "cacerts",
123 Self::SimpleEnroll => "simpleenroll",
124 Self::SimpleReenroll => "simplereenroll",
125 Self::FullCmc => "fullcmc",
126 Self::ServerKeygen => "serverkeygen",
127 Self::CsrAttrs => "csrattrs",
128 }
129 }
130
131 pub fn requires_mtls(&self) -> bool {
133 match self {
134 Self::CaCerts | Self::CsrAttrs => false,
135 Self::SimpleEnroll | Self::SimpleReenroll | Self::FullCmc | Self::ServerKeygen => true,
136 }
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn test_operation_paths() {
146 assert_eq!(EstOperation::CaCerts.path(), "cacerts");
147 assert_eq!(EstOperation::SimpleEnroll.path(), "simpleenroll");
148 assert_eq!(EstOperation::SimpleReenroll.path(), "simplereenroll");
149 assert_eq!(EstOperation::FullCmc.path(), "fullcmc");
150 assert_eq!(EstOperation::ServerKeygen.path(), "serverkeygen");
151 assert_eq!(EstOperation::CsrAttrs.path(), "csrattrs");
152 }
153
154 #[test]
155 fn test_mtls_requirements() {
156 assert!(!EstOperation::CaCerts.requires_mtls());
157 assert!(!EstOperation::CsrAttrs.requires_mtls());
158 assert!(EstOperation::SimpleEnroll.requires_mtls());
159 assert!(EstOperation::SimpleReenroll.requires_mtls());
160 assert!(EstOperation::FullCmc.requires_mtls());
161 assert!(EstOperation::ServerKeygen.requires_mtls());
162 }
163}