rasn_cms/tsp.rs
1//! [RFC 3161](https://www.rfc-editor.org/rfc/rfc3161) Time Stamp Protocol (TSP).
2
3use crate::ContentInfo;
4use rasn::error::DecodeError;
5use rasn::prelude::*;
6use rasn::types::OctetString;
7use rasn::{AsnType, Decode, Encode};
8use rasn_pkix::{AlgorithmIdentifier, Extensions, GeneralName};
9
10/// Time-stamp token eContentType of EncapsulatedContentInfo in the SignedData.
11pub const TST_INFO: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS9_SMIME_CT_TSTINFO;
12
13fn default_false() -> bool {
14 false
15}
16
17/** Time-stamp request.
18
19[RFC 3161 2.4.1](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.1):
20
21```text
22 TimeStampReq ::= SEQUENCE {
23 version INTEGER { v1(1) },
24 messageImprint MessageImprint,
25 --a hash algorithm OID and the hash value of the data to be
26 --time-stamped
27 reqPolicy TSAPolicyId OPTIONAL,
28 nonce INTEGER OPTIONAL,
29 certReq BOOLEAN DEFAULT FALSE,
30 extensions [0] IMPLICIT Extensions OPTIONAL }
31```
32*/
33#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
34pub struct TimeStampReq {
35 pub version: u64,
36 pub message_imprint: MessageImprint,
37 pub req_policy: Option<TsaPolicyId>,
38 pub nonce: Option<Integer>,
39 #[rasn(default = "default_false")]
40 pub cert_req: bool,
41 #[rasn(tag(0))]
42 pub extensions: Option<Extensions>,
43}
44
45/** Fingerprint of data to protect with a time-stamp.
46
47[RFC 3161 2.4.1](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.1):
48
49```text
50 MessageImprint ::= SEQUENCE {
51 hashAlgorithm AlgorithmIdentifier,
52 hashedMessage OCTET STRING }
53```
54*/
55#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
56pub struct MessageImprint {
57 pub hash_algorithm: AlgorithmIdentifier,
58 pub hashed_message: OctetString,
59}
60
61/** A policy that applies to a time-stamp.
62
63[RFC 3161 2.4.1](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.1):
64
65```text
66 TSAPolicyId ::= OBJECT IDENTIFIER
67```
68*/
69pub type TsaPolicyId = ObjectIdentifier;
70
71/** Time-stamp response.
72
73[RFC 3161 2.4.2](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2):
74
75```text
76 TimeStampResp ::= SEQUENCE {
77 status PKIStatusInfo,
78 timeStampToken TimeStampToken OPTIONAL }
79```
80*/
81#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
82pub struct TimeStampResp {
83 pub status: PkiStatusInfo,
84 pub time_stamp_token: Option<TimeStampToken>,
85}
86
87/** Time-stamp response status.
88
89[RFC 3161 2.4.2](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2):
90
91```text
92 PKIStatusInfo ::= SEQUENCE {
93 status PKIStatus,
94 statusString PKIFreeText OPTIONAL,
95 failInfo PKIFailureInfo OPTIONAL }
96```
97*/
98#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
99pub struct PkiStatusInfo {
100 pub status: PkiStatus,
101 pub status_string: Option<PkiFreeText>,
102 pub fail_info: Option<PkiFailureInfo>,
103}
104
105/** Time-stamp response status code.
106
107[RFC 3161 2.4.2](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2):
108
109```text
110 PKIStatus ::= INTEGER {
111 granted (0),
112 -- when the PKIStatus contains the value zero a TimeStampToken, as
113 requested, is present.
114 grantedWithMods (1),
115 -- when the PKIStatus contains the value one a TimeStampToken,
116 with modifications, is present.
117 rejection (2),
118 waiting (3),
119 revocationWarning (4),
120 -- this message contains a warning that a revocation is
121 -- imminent
122 revocationNotification (5)
123 -- notification that a revocation has occurred }
124```
125*/
126#[derive(AsnType, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
127#[rasn(enumerated)]
128pub enum PkiStatus {
129 /// A TimeStampToken, as requested, is present.
130 Granted = 0,
131 /// A TimeStampToken, with modifications, is present.
132 GrantedWithMods = 1,
133 Rejection = 2,
134 Waiting = 3,
135 /// This message contains a warning that a revocation is imminent.
136 RevocationWarning = 4,
137 /// Notification that a revocation has occurred.
138 RevocationNotification = 5,
139}
140
141impl Decode for PkiStatus {
142 fn decode_with_tag_and_constraints<D: Decoder>(
143 decoder: &mut D,
144 _tag: Tag,
145 constraints: Constraints,
146 ) -> Result<Self, D::Error> {
147 let discriminant = decoder.decode_integer::<isize>(Tag::INTEGER, constraints)?;
148 let pki_status = PkiStatus::from_discriminant(discriminant).ok_or_else(|| {
149 DecodeError::discriminant_value_not_found(discriminant, decoder.codec())
150 })?;
151 Ok(pki_status)
152 }
153}
154
155impl Encode for PkiStatus {
156 fn encode_with_tag_and_constraints<'b, E: Encoder<'b>>(
157 &self,
158 encoder: &mut E,
159 _tag: Tag,
160 constraints: Constraints,
161 identifier: Identifier,
162 ) -> Result<(), <E as Encoder<'b>>::Error> {
163 encoder.encode_integer(Tag::INTEGER, constraints, &self.discriminant(), identifier)?;
164 Ok(())
165 }
166}
167
168/** Time-stamp response status free text.
169
170[RFC 3161 2.4.2](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2):
171
172```text
173 PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
174 -- text encoded as UTF-8 String (note: each UTF8String SHOULD
175 -- include an RFC 1766 language tag to indicate the language
176 -- of the contained text)
177```
178*/
179pub type PkiFreeText = SequenceOf<Utf8String>;
180
181/** Time-stamp response status failure reason.
182
183[RFC 3161 2.4.2](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2):
184
185```text
186 PKIFailureInfo ::= BIT STRING {
187 badAlg (0),
188 -- unrecognized or unsupported Algorithm Identifier
189 badRequest (2),
190 -- transaction not permitted or supported
191 badDataFormat (5),
192 -- the data submitted has the wrong format
193 timeNotAvailable (14),
194 -- the TSA's time source is not available
195 unacceptedPolicy (15),
196 -- the requested TSA policy is not supported by the TSA
197 unacceptedExtension (16),
198 -- the requested extension is not supported by the TSA
199 addInfoNotAvailable (17)
200 -- the additional information requested could not be understood
201 -- or is not available
202 systemFailure (25)
203 -- the request cannot be handled due to system failure }
204```
205*/
206pub type PkiFailureInfo = BitString;
207
208/** Time-stamp token.
209
210[RFC 3161 2.4.2](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2):
211
212```text
213 TimeStampToken ::= ContentInfo
214 -- contentType is id-signedData ([CMS])
215 -- content is SignedData ([CMS])
216```
217*/
218pub type TimeStampToken = ContentInfo;
219
220/** Time-stamp token information.
221
222[RFC 3161 2.4.2](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2):
223
224```text
225 TSTInfo ::= SEQUENCE {
226 version INTEGER { v1(1) },
227 policy TSAPolicyId,
228 messageImprint MessageImprint,
229 -- MUST have the same value as the similar field in
230 -- TimeStampReq
231 serialNumber INTEGER,
232 -- Time-Stamping users MUST be ready to accommodate integers
233 -- up to 160 bits.
234 genTime GeneralizedTime,
235 accuracy Accuracy OPTIONAL,
236 ordering BOOLEAN DEFAULT FALSE,
237 nonce INTEGER OPTIONAL,
238 -- MUST be present if the similar field was present
239 -- in TimeStampReq. In that case it MUST have the same value.
240 tsa [0] GeneralName OPTIONAL,
241 extensions [1] IMPLICIT Extensions OPTIONAL }
242```
243*/
244#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
245pub struct TstInfo {
246 pub version: Integer,
247 pub policy: TsaPolicyId,
248 pub message_imprint: MessageImprint,
249 pub serial_number: Integer,
250 pub gen_time: GeneralizedTime,
251 pub accuracy: Option<Accuracy>,
252 #[rasn(default = "default_false")]
253 pub ordering: bool,
254 pub nonce: Option<Integer>,
255 #[rasn(tag(explicit(0)))]
256 pub tsa: Option<GeneralName>,
257 #[rasn(tag(1))]
258 pub extensions: Option<Extensions>,
259}
260
261/** Accuracy of the time (`genTime`) in [TstInfo].
262
263[RFC 3161 2.4.2](https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2):
264
265```text
266 Accuracy ::= SEQUENCE {
267 seconds INTEGER OPTIONAL,
268 millis [0] INTEGER (1..999) OPTIONAL,
269 micros [1] INTEGER (1..999) OPTIONAL }
270```
271*/
272#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
273pub struct Accuracy {
274 pub seconds: Option<Integer>,
275 #[rasn(tag(0))]
276 pub millis: Option<Integer>,
277 #[rasn(tag(1))]
278 pub micros: Option<Integer>,
279}