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}