1use {
8 crate::asn1::{rfc4210::PkiFreeText, rfc5652::ContentInfo},
9 bcder::{
10 decode::{Constructed, DecodeError, Primitive, Source},
11 encode::{self, PrimitiveContent, Values},
12 ConstOid, Integer, OctetString, Oid, Tag,
13 },
14 x509_certificate::{
15 asn1time::GeneralizedTime,
16 rfc3280::GeneralName,
17 rfc5280::{AlgorithmIdentifier, Extensions},
18 },
19};
20
21pub const OID_CONTENT_TYPE_TST_INFO: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 16, 1, 4]);
25
26pub const OID_TIME_STAMP_TOKEN: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 16, 2, 14]);
30
31#[derive(Clone, Debug, Eq, PartialEq)]
45pub struct TimeStampReq {
46 pub version: Integer,
47 pub message_imprint: MessageImprint,
48 pub req_policy: Option<TsaPolicyId>,
49 pub nonce: Option<Integer>,
50 pub cert_req: Option<bool>,
51 pub extensions: Option<Extensions>,
52}
53
54impl TimeStampReq {
55 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
56 cons.take_sequence(|cons| {
57 let version = Integer::take_from(cons)?;
58 let message_imprint = MessageImprint::take_from(cons)?;
59 let req_policy = TsaPolicyId::take_opt_from(cons)?;
60 let nonce =
61 cons.take_opt_primitive_if(Tag::INTEGER, |prim| Integer::from_primitive(prim))?;
62 let cert_req = cons.take_opt_bool()?;
63 let extensions =
64 cons.take_opt_constructed_if(Tag::CTX_0, |cons| Extensions::take_from(cons))?;
65
66 Ok(Self {
67 version,
68 message_imprint,
69 req_policy,
70 nonce,
71 cert_req,
72 extensions,
73 })
74 })
75 }
76
77 pub fn encode_ref(&self) -> impl Values + '_ {
78 encode::sequence((
79 (&self.version).encode(),
80 self.message_imprint.encode_ref(),
81 self.req_policy
82 .as_ref()
83 .map(|req_policy| req_policy.encode_ref()),
84 self.nonce.as_ref().map(|nonce| nonce.encode()),
85 self.cert_req.as_ref().map(|cert_req| cert_req.encode_ref()),
86 self.extensions
87 .as_ref()
88 .map(|extensions| extensions.encode_ref_as(Tag::CTX_0)),
89 ))
90 }
91}
92
93#[derive(Clone, Debug, Eq, PartialEq)]
101pub struct MessageImprint {
102 pub hash_algorithm: AlgorithmIdentifier,
103 pub hashed_message: OctetString,
104}
105
106impl MessageImprint {
107 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
108 cons.take_sequence(|cons| {
109 let hash_algorithm = AlgorithmIdentifier::take_from(cons)?;
110 let hashed_message = OctetString::take_from(cons)?;
111
112 Ok(Self {
113 hash_algorithm,
114 hashed_message,
115 })
116 })
117 }
118
119 pub fn encode_ref(&self) -> impl Values + '_ {
120 encode::sequence((&self.hash_algorithm, self.hashed_message.encode_ref()))
121 }
122}
123
124pub type TsaPolicyId = Oid;
125
126#[derive(Clone, Debug, Eq, PartialEq)]
134pub struct TimeStampResp {
135 pub status: PkiStatusInfo,
136 pub time_stamp_token: Option<TimeStampToken>,
137}
138
139impl TimeStampResp {
140 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
141 cons.take_sequence(|cons| {
142 let status = PkiStatusInfo::take_from(cons)?;
143 let time_stamp_token = TimeStampToken::take_opt_from(cons)?;
144
145 Ok(Self {
146 status,
147 time_stamp_token,
148 })
149 })
150 }
151
152 pub fn encode_ref(&self) -> impl Values + '_ {
153 encode::sequence((
154 self.status.encode_ref(),
155 if let Some(time_stamp_token) = &self.time_stamp_token {
156 Some(time_stamp_token)
157 } else {
158 None
159 },
160 ))
161 }
162}
163
164#[derive(Clone, Debug, Eq, PartialEq)]
173pub struct PkiStatusInfo {
174 pub status: PkiStatus,
175 pub status_string: Option<PkiFreeText>,
176 pub fail_info: Option<PkiFailureInfo>,
177}
178
179impl PkiStatusInfo {
180 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
181 cons.take_sequence(|cons| {
182 let status = PkiStatus::take_from(cons)?;
183 let status_string = PkiFreeText::take_opt_from(cons)?;
184 let fail_info = PkiFailureInfo::take_opt_from(cons)?;
185
186 Ok(Self {
187 status,
188 status_string,
189 fail_info,
190 })
191 })
192 }
193
194 pub fn encode_ref(&self) -> impl Values + '_ {
195 encode::sequence((
196 self.status.encode(),
197 self.status_string
198 .as_ref()
199 .map(|status_string| status_string.encode_ref()),
200 self.fail_info.as_ref().map(|fail_info| fail_info.encode()),
201 ))
202 }
203}
204
205#[derive(Clone, Copy, Debug, Eq, PartialEq)]
229pub enum PkiStatus {
230 Granted = 0,
231 GrantedWithMods = 1,
232 Rejection = 2,
233 Waiting = 3,
234 RevocationWarning = 4,
235 RevocationNotification = 5,
236}
237
238impl PkiStatus {
239 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
240 match cons.take_primitive_if(Tag::INTEGER, Integer::i8_from_primitive)? {
241 0 => Ok(Self::Granted),
242 1 => Ok(Self::GrantedWithMods),
243 2 => Ok(Self::Rejection),
244 3 => Ok(Self::Waiting),
245 4 => Ok(Self::RevocationWarning),
246 5 => Ok(Self::RevocationNotification),
247 _ => Err(cons.content_err("unknown PKIStatus value")),
248 }
249 }
250
251 pub fn encode(self) -> impl Values {
252 u8::from(self).encode()
253 }
254}
255
256impl From<PkiStatus> for u8 {
257 fn from(v: PkiStatus) -> u8 {
258 match v {
259 PkiStatus::Granted => 0,
260 PkiStatus::GrantedWithMods => 1,
261 PkiStatus::Rejection => 2,
262 PkiStatus::Waiting => 3,
263 PkiStatus::RevocationWarning => 4,
264 PkiStatus::RevocationNotification => 5,
265 }
266 }
267}
268
269#[derive(Clone, Copy, Debug, Eq, PartialEq)]
292pub enum PkiFailureInfo {
293 BadAlg = 0,
294 BadRequest = 1,
295 BadDataFormat = 5,
296 TimeNotAvailable = 14,
297 UnacceptedPolicy = 15,
298 UnacceptedExtension = 16,
299 AddInfoNotAvailable = 17,
300 SystemFailure = 25,
301}
302
303impl PkiFailureInfo {
304 pub fn take_opt_from<S: Source>(
305 cons: &mut Constructed<S>,
306 ) -> Result<Option<Self>, DecodeError<S::Error>> {
307 cons.take_opt_primitive_if(Tag::INTEGER, Self::from_primitive)
308 }
309
310 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
311 cons.take_primitive_if(Tag::INTEGER, Self::from_primitive)
312 }
313
314 pub fn from_primitive<S: Source>(
315 prim: &mut Primitive<S>,
316 ) -> Result<Self, DecodeError<S::Error>> {
317 match Integer::i8_from_primitive(prim)? {
318 0 => Ok(Self::BadAlg),
319 1 => Ok(Self::BadRequest),
320 5 => Ok(Self::BadDataFormat),
321 14 => Ok(Self::TimeNotAvailable),
322 15 => Ok(Self::UnacceptedPolicy),
323 16 => Ok(Self::UnacceptedExtension),
324 17 => Ok(Self::AddInfoNotAvailable),
325 25 => Ok(Self::SystemFailure),
326 _ => Err(prim.content_err("Unknown PKIFailureInfo value")),
327 }
328 }
329
330 pub fn encode(self) -> impl Values {
331 u8::from(self).encode()
332 }
333}
334
335impl From<PkiFailureInfo> for u8 {
336 fn from(v: PkiFailureInfo) -> u8 {
337 match v {
338 PkiFailureInfo::BadAlg => 0,
339 PkiFailureInfo::BadRequest => 1,
340 PkiFailureInfo::BadDataFormat => 5,
341 PkiFailureInfo::TimeNotAvailable => 14,
342 PkiFailureInfo::UnacceptedPolicy => 15,
343 PkiFailureInfo::UnacceptedExtension => 16,
344 PkiFailureInfo::AddInfoNotAvailable => 17,
345 PkiFailureInfo::SystemFailure => 25,
346 }
347 }
348}
349
350pub type TimeStampToken = ContentInfo;
356
357#[derive(Clone, Debug, Eq, PartialEq)]
379pub struct TstInfo {
380 pub version: Integer,
381 pub policy: TsaPolicyId,
382 pub message_imprint: MessageImprint,
383 pub serial_number: Integer,
384 pub gen_time: GeneralizedTime,
385 pub accuracy: Option<Accuracy>,
386 pub ordering: Option<bool>,
387 pub nonce: Option<Integer>,
388 pub tsa: Option<GeneralName>,
389 pub extensions: Option<Extensions>,
390}
391
392impl TstInfo {
393 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
394 cons.take_sequence(|cons| {
395 let version = Integer::take_from(cons)?;
396 let policy = TsaPolicyId::take_from(cons)?;
397 let message_imprint = MessageImprint::take_from(cons)?;
398 let serial_number = Integer::take_from(cons)?;
399 let gen_time = GeneralizedTime::take_from_allow_fractional_z(cons)?;
400 let accuracy = Accuracy::take_opt_from(cons)?;
401 let ordering = cons.take_opt_bool()?;
402 let nonce =
403 cons.take_opt_primitive_if(Tag::INTEGER, |prim| Integer::from_primitive(prim))?;
404 let tsa =
405 cons.take_opt_constructed_if(Tag::CTX_0, |cons| GeneralName::take_from(cons))?;
406 let extensions =
407 cons.take_opt_constructed_if(Tag::CTX_1, |cons| Extensions::take_from(cons))?;
408
409 Ok(Self {
410 version,
411 policy,
412 message_imprint,
413 serial_number,
414 gen_time,
415 accuracy,
416 ordering,
417 nonce,
418 tsa,
419 extensions,
420 })
421 })
422 }
423
424 pub fn encode_ref(&self) -> impl Values + '_ {
425 encode::sequence((
426 (&self.version).encode(),
427 self.policy.encode_ref(),
428 self.message_imprint.encode_ref(),
429 (&self.serial_number).encode(),
430 self.gen_time.encode_ref(),
431 self.accuracy.as_ref().map(|accuracy| accuracy.encode_ref()),
432 self.ordering.as_ref().map(|ordering| ordering.encode_ref()),
433 self.nonce.as_ref().map(|nonce| nonce.encode()),
434 self.tsa
435 .as_ref()
436 .map(|tsa| tsa.encode_ref().explicit(Tag::CTX_0)),
437 self.extensions
438 .as_ref()
439 .map(|extensions| extensions.encode_ref_as(Tag::CTX_1)),
440 ))
441 }
442}
443
444#[derive(Clone, Debug, Eq, PartialEq)]
453pub struct Accuracy {
454 pub seconds: Option<Integer>,
455 pub millis: Option<Integer>,
456 pub micros: Option<Integer>,
457}
458
459impl Accuracy {
460 pub fn take_opt_from<S: Source>(
461 cons: &mut Constructed<S>,
462 ) -> Result<Option<Self>, DecodeError<S::Error>> {
463 cons.take_opt_sequence(|cons| Self::from_sequence(cons))
464 }
465
466 pub fn from_sequence<S: Source>(
467 cons: &mut Constructed<S>,
468 ) -> Result<Self, DecodeError<S::Error>> {
469 let seconds =
470 cons.take_opt_primitive_if(Tag::INTEGER, |prim| Integer::from_primitive(prim))?;
471 let millis = cons.take_opt_constructed_if(Tag::CTX_0, |cons| Integer::take_from(cons))?;
472 let micros = cons.take_opt_constructed_if(Tag::CTX_1, |cons| Integer::take_from(cons))?;
473
474 Ok(Self {
475 seconds,
476 millis,
477 micros,
478 })
479 }
480
481 pub fn encode_ref(&self) -> impl Values + '_ {
482 encode::sequence((
483 self.seconds.as_ref().map(|seconds| seconds.encode()),
484 self.millis.as_ref().map(|millis| millis.encode()),
485 self.micros.as_ref().map(|micros| micros.encode()),
486 ))
487 }
488}