structured_cms/timestamp/
request.rs1use super::{HashAlgorithmReading, MessageImprint};
4use crate::{Error, ErrorCode, Result};
5use structured_asn1::{Element, Integer, Oid, Parser, Reader, Span, Tag, universal};
6use structured_pkix::Extensions;
7
8#[derive(Debug)]
14pub struct Request<'a> {
15 imprint: MessageImprint<'a>,
16 policy: Option<Oid<'a>>,
17 nonce: Option<Integer<'a>>,
18 cert_req: bool,
19 extensions: Option<Extensions<'a>>,
20 span: Span,
21 parser: &'a Parser,
22}
23
24impl<'a> Request<'a> {
25 pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
30 const FIELD: &str = "timeStampReq";
31 if element.tag() != Tag::constructed(universal::SEQUENCE) {
32 return Err(Error::schema(
33 ErrorCode::UnexpectedTag,
34 FIELD,
35 element.span().start,
36 ));
37 }
38 let mut inside = parent
39 .enter(element)
40 .map_err(|source| Error::encoding(source, FIELD))?;
41 let version = crate::signer::required(&mut inside, "timeStampReq.version")?;
42 if version.tag() != Tag::primitive(universal::INTEGER) {
43 return Err(Error::schema(
44 ErrorCode::UnexpectedTag,
45 "timeStampReq.version",
46 version.span().start,
47 ));
48 }
49 let number = inside
50 .integer(&version)
51 .map_err(|source| Error::encoding(source, "timeStampReq.version"))?;
52 if number.as_u64() != Some(1) {
53 return Err(Error::schema(
54 ErrorCode::UnsupportedVersion,
55 "timeStampReq.version",
56 version.span().start,
57 ));
58 }
59 let imprint = crate::signer::required(&mut inside, "timeStampReq.messageImprint")?;
60 let imprint = MessageImprint::read_fields(
61 &inside,
62 &imprint,
63 super::imprint::ImprintFields {
64 enclosing: "timeStampReq.messageImprint",
65 algorithm: "timeStampReq.messageImprint.hashAlgorithm",
66 hashed: "timeStampReq.messageImprint.hashedMessage",
67 },
68 )?;
69 if !imprint.faults().is_empty()
70 || !matches!(imprint.algorithm(), HashAlgorithmReading::Identifier(_))
71 {
72 return Err(Error::schema(
73 ErrorCode::MalformedValue,
74 "timeStampReq.messageImprint",
75 imprint.span().start,
76 ));
77 }
78 let mut output = Self {
79 imprint,
80 policy: None,
81 nonce: None,
82 cert_req: false,
83 extensions: None,
84 span: element.span(),
85 parser: parent.parser(),
86 };
87 let mut previous = 0;
88 while let Some(element) = inside
89 .next_element()
90 .map_err(|source| Error::encoding(source, FIELD))?
91 {
92 let ordinal = match element.tag() {
93 tag if tag == Tag::primitive(universal::OID) => 1,
94 tag if tag == Tag::primitive(universal::INTEGER) => 2,
95 tag if tag == Tag::primitive(universal::BOOLEAN) => 3,
96 tag if tag == Tag::context(true, 0) => 4,
97 _ => {
98 return Err(Error::schema(
99 ErrorCode::UnknownField,
100 FIELD,
101 element.span().start,
102 ));
103 }
104 };
105 if ordinal <= previous {
106 return Err(Error::schema(
107 if ordinal == previous {
108 ErrorCode::DuplicateField
109 } else {
110 ErrorCode::FieldOrder
111 },
112 FIELD,
113 element.span().start,
114 ));
115 }
116 previous = ordinal;
117 output.read_optional(&inside, &element, ordinal)?;
118 }
119 Ok(output)
120 }
121
122 fn read_optional(
123 &mut self,
124 inside: &Reader<'a>,
125 element: &Element<'a>,
126 ordinal: u8,
127 ) -> Result<()> {
128 match ordinal {
129 1 => {
130 self.policy = Some(
131 inside
132 .oid(element)
133 .map_err(|source| Error::encoding(source, "timeStampReq.reqPolicy"))?,
134 );
135 }
136 2 => {
137 self.nonce = Some(
138 inside
139 .integer(element)
140 .map_err(|source| Error::encoding(source, "timeStampReq.nonce"))?,
141 );
142 }
143 3 => {
144 self.cert_req = inside
145 .boolean(element)
146 .map_err(|source| Error::encoding(source, "timeStampReq.certReq"))?;
147 if !self.cert_req && inside.encoding() == structured_asn1::Encoding::Der {
150 return Err(Error::schema(
151 ErrorCode::DefaultWritten,
152 "timeStampReq.certReq",
153 element.span().start,
154 ));
155 }
156 }
157 4 => {
158 self.extensions = Some(
159 Extensions::read_implicit(inside, element, 0, "timeStampReq.extensions")
160 .map_err(Error::pkix)?,
161 );
162 }
163 _ => unreachable!("ordinal comes from the four schema tags above"),
164 }
165 Ok(())
166 }
167
168 #[must_use]
170 pub fn imprint(&self) -> &MessageImprint<'a> {
171 &self.imprint
172 }
173 #[must_use]
175 pub fn policy(&self) -> Option<Oid<'a>> {
176 self.policy
177 }
178 #[must_use]
180 pub fn nonce(&self) -> Option<Integer<'a>> {
181 self.nonce
182 }
183 #[must_use]
185 pub fn cert_req(&self) -> bool {
186 self.cert_req
187 }
188 #[must_use]
190 pub fn extensions(&self) -> Option<&Extensions<'a>> {
191 self.extensions.as_ref()
192 }
193 #[must_use]
195 pub fn span(&self) -> Span {
196 self.span
197 }
198 #[must_use]
200 pub fn same_session(&self, parent: &Reader<'_>) -> bool {
201 core::ptr::eq(self.parser, parent.parser())
202 }
203}