1use asn1_der::{
5 typed::{DerDecodable, Sequence},
6 DerObject,
7};
8use chrono::{Datelike, Timelike};
9use tracing::{error, trace};
10
11use crate::err::OcspError;
12use crate::oid::{b2i_oid, d2i_oid, i2b_oid};
13
14pub type Bytes = Vec<u8>;
16
17pub(crate) const ASN1_EXPLICIT_0: u8 = 0xa0;
19pub(crate) const ASN1_EXPLICIT_1: u8 = 0xa1;
21pub(crate) const ASN1_EXPLICIT_2: u8 = 0xa2;
23pub(crate) const ASN1_NULL: u8 = 0x05;
25pub(crate) const ASN1_OID: u8 = 0x06;
27pub(crate) const ASN1_OID_PADDING: [u8; 2] = [0x05, 0x00];
29pub(crate) const ASN1_SEQUENCE: u8 = 0x30;
31pub(crate) const ASN1_OCTET: u8 = 0x04;
33pub(crate) const ASN1_INTEGER: u8 = 0x02;
35pub(crate) const ASN1_IA5STRING: u8 = 0x16;
37pub(crate) const ASN1_GENERALIZED_TIME: u8 = 0x18;
39pub(crate) const ASN1_ENUMERATED: u8 = 0x0a;
41pub(crate) const ASN1_BIT_STRING: u8 = 0x03;
43
44pub trait TryIntoSequence<'d> {
46 type Error;
48 fn try_into(&'d self) -> Result<Sequence<'d>, Self::Error>;
50}
51
52impl<'d> TryIntoSequence<'d> for DerObject<'d> {
53 type Error = OcspError;
54 fn try_into(&self) -> Result<Sequence<'d>, Self::Error> {
55 Sequence::decode(self.raw()).map_err(OcspError::Asn1DecodingError)
56 }
57}
58
59impl<'d> TryIntoSequence<'d> for Bytes {
60 type Error = OcspError;
61 fn try_into(&'d self) -> Result<Sequence<'d>, Self::Error> {
62 Sequence::decode(self).map_err(OcspError::Asn1DecodingError)
63 }
64}
65
66impl<'d> TryIntoSequence<'d> for &[u8] {
67 type Error = OcspError;
68 fn try_into(&'d self) -> Result<Sequence<'d>, Self::Error> {
69 Sequence::decode(self).map_err(OcspError::Asn1DecodingError)
70 }
71}
72
73pub(crate) fn asn1_encode_length(len: usize) -> Result<Bytes, OcspError> {
76 match len {
77 0..=127 => Ok(vec![len as u8]),
78 _ => {
79 let v = len.to_be_bytes().to_vec();
80 let v: Bytes = v.into_iter().skip_while(|n| *n == 0).collect();
82
83 if v.len() > 127 {
85 return Err(OcspError::Asn1LengthOverflow(v.len()));
86 }
87 let l = 0x80 + v.len() as u8;
88 let l = vec![l];
89 Ok(l.into_iter().chain(v.into_iter()).collect())
90 }
91 }
92}
93
94pub(crate) fn asn1_encode_octet(data: &[u8]) -> Result<Bytes, OcspError> {
96 let mut tlv = vec![ASN1_OCTET];
97 let len = asn1_encode_length(data.len())?;
98 tlv.extend(len);
99 tlv.extend(data);
100 Ok(tlv)
101}
102
103pub(crate) fn asn1_encode_integer(data: &[u8]) -> Result<Bytes, OcspError> {
105 let mut tlv = vec![ASN1_INTEGER];
106 let len = asn1_encode_length(data.len())?;
107 tlv.extend(len);
108 tlv.extend(data);
109 Ok(tlv)
110}
111
112pub(crate) fn asn1_encode_bit_string(data: &[u8]) -> Result<Bytes, OcspError> {
114 let mut tlv = vec![ASN1_BIT_STRING];
115 let len = asn1_encode_length(data.len())?;
116 tlv.extend(len);
117 tlv.extend(data);
118 Ok(tlv)
119}
120
121#[derive(Debug, Copy, Clone)]
124pub struct GeneralizedTime {
125 year: i32,
126 month: u32,
127 day: u32,
128 hour: u32,
129 min: u32,
130 sec: u32,
131 }
133
134impl GeneralizedTime {
135 pub fn new(
137 year: i32,
138 month: u32,
139 day: u32,
140 hour: u32,
141 min: u32,
142 sec: u32,
143 ) -> Result<Self, OcspError> {
144 let dt = chrono::NaiveDate::from_ymd_opt(year, month, day)
147 .ok_or(OcspError::GenInvalidDate(year, month, day))?;
148 let _ = dt
149 .and_hms_opt(hour, min, sec)
150 .ok_or(OcspError::GenInvalidTime(hour, min, sec))?;
151
152 Ok(GeneralizedTime {
153 year,
154 month,
155 day,
156 hour,
157 min,
158 sec,
159 })
160 }
161
162 pub fn now() -> Self {
164 let now = chrono::offset::Utc::now();
165
166 GeneralizedTime {
167 year: now.year(),
168 month: now.month(),
169 day: now.day(),
170 hour: now.hour(),
171 min: now.minute(),
172 sec: now.second(),
173 }
175 }
176
177 pub fn to_der_utc(&self) -> Result<Bytes, OcspError> {
180 let v = format!(
181 "{}{:02}{:02}{:02}{:02}{:02}Z",
182 self.year, self.month, self.day, self.hour, self.min, self.sec
183 )
184 .as_bytes()
185 .to_vec();
186 let l = asn1_encode_length(v.len())?;
187 let mut t = vec![ASN1_GENERALIZED_TIME];
188 t.extend(l);
189 t.extend(v);
190 Ok(t)
191 }
192}
193
194#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
198pub struct Oid {
199 pub(crate) index: usize,
200}
201
202impl Oid {
203 pub fn parse(oid: &[u8]) -> Result<Self, OcspError> {
205 let oid_hex = hex::encode(oid);
206 trace!("Parsing oid {}", oid_hex);
207 let s = oid.try_into()?;
208
209 if s.len() != 2 {
210 error!(
211 "Provided oid contains {} items in sequence, expecting 2",
212 s.len()
213 );
214 return Err(OcspError::Asn1LengthError("OID"));
215 }
216
217 let id = s.get(0).map_err(OcspError::Asn1DecodingError)?;
218 let nil = s.get(1).map_err(OcspError::Asn1DecodingError)?;
219 if id.tag() != ASN1_OID || nil.tag() != ASN1_NULL {
220 error!(
221 "Provided oid sequence tags are {} and {}, expecting 0x06 and 0x05",
222 id.tag(),
223 nil.tag()
224 );
225 return Err(OcspError::Asn1MismatchError("OID"));
226 }
227
228 let u = match b2i_oid(id.value()) {
229 None => return Err(OcspError::Asn1OidUnknown),
230 Some(u) => u,
231 };
232
233 trace!("Oid {} successfully decoded to internal {}", oid_hex, u);
234 Ok(Oid { index: u })
235 }
236
237 pub fn new_from_dot(name_dot_notation: &str) -> Result<Self, OcspError> {
239 d2i_oid(name_dot_notation).ok_or(OcspError::Asn1OidUnknown)
241 }
242
243 pub fn to_der_with_null(&self) -> Result<Bytes, OcspError> {
245 trace!("Encoding oid index {}", self.index);
246 let val_oid = i2b_oid(self)?;
247 let len_oid = asn1_encode_length(val_oid.len())?;
248 let mut tlv_oid = vec![ASN1_OID];
249 tlv_oid.extend(len_oid);
250 tlv_oid.extend(val_oid);
251 tlv_oid.extend(ASN1_OID_PADDING);
252 let len_seq = asn1_encode_length(tlv_oid.len())?;
253 let mut tlv_seq_oid = vec![ASN1_SEQUENCE];
254 tlv_seq_oid.extend(len_seq);
255 tlv_seq_oid.extend(tlv_oid);
256
257 trace!("Internal oid {} successfully encoded", self.index);
258 Ok(tlv_seq_oid)
259 }
260
261 pub fn to_der_raw(&self) -> Result<Bytes, OcspError> {
265 trace!("Encoding oid without sequence index {}", self.index);
266 let val_oid = i2b_oid(self)?;
267 let len_oid = asn1_encode_length(val_oid.len())?;
268 let mut tlv_oid = vec![ASN1_OID];
269 tlv_oid.extend(len_oid);
270 tlv_oid.extend(val_oid);
271
272 trace!(
273 "Internal oid {} successfully encoded without padding",
274 self.index
275 );
276 Ok(tlv_oid)
277 }
278}
279
280#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
282pub struct CertId {
283 pub hash_algo: Oid,
285 pub issuer_name_hash: Bytes,
287 pub issuer_key_hash: Bytes,
289 pub serial_num: Bytes,
291}
292
293impl CertId {
294 pub fn parse(cid: &[u8]) -> Result<Self, OcspError> {
296 let cid_hex = hex::encode(cid);
297 trace!("Parsing cid {}", cid_hex);
298 let s = cid.try_into()?;
299
300 if s.len() != 4 {
301 error!(
302 "Provided cid contains {} items in sequence, expecting 4",
303 s.len()
304 );
305 return Err(OcspError::Asn1LengthError("CID"));
306 }
307
308 let oid = s.get(0).map_err(OcspError::Asn1DecodingError)?;
309 let name_hash = s.get(1).map_err(OcspError::Asn1DecodingError)?;
310 let key_hash = s.get(2).map_err(OcspError::Asn1DecodingError)?;
311 let sn = s.get(3).map_err(OcspError::Asn1DecodingError)?;
312
313 if oid.tag() != ASN1_SEQUENCE
314 || name_hash.tag() != ASN1_OCTET
315 || key_hash.tag() != ASN1_OCTET
316 || sn.tag() != ASN1_INTEGER
317 {
318 error!(
319 "Provided cid sequence tags are {}, {}, {} and {}, expecting 0x30, 0x04, 0x04, 0x02",
320 oid.tag(),
321 name_hash.tag(),
322 key_hash.tag(),
323 sn.tag()
324 );
325 return Err(OcspError::Asn1MismatchError("CID"));
326 }
327
328 let oid = Oid::parse(oid.raw())?;
329 let name_hash = name_hash.value().to_vec();
330 let key_hash = key_hash.value().to_vec();
331 let sn = sn.value().to_vec();
332
333 trace!("Cid {} successfully decoded", cid_hex);
334 Ok(CertId {
335 hash_algo: oid,
336 issuer_name_hash: name_hash,
337 issuer_key_hash: key_hash,
338 serial_num: sn,
339 })
340 }
341
342 pub fn new(oid: Oid, name_hash: &[u8], key_hash: &[u8], sn: &[u8]) -> Self {
344 CertId {
345 hash_algo: oid,
346 issuer_name_hash: name_hash.to_vec(),
347 issuer_key_hash: key_hash.to_vec(),
348 serial_num: sn.to_vec(),
349 }
350 }
351
352 pub fn to_der(&self) -> Result<Bytes, OcspError> {
354 trace!("Encoding cid with sn {}", hex::encode(&self.serial_num));
355
356 let mut oid = self.hash_algo.to_der_with_null()?;
357 let name = asn1_encode_octet(&self.issuer_name_hash)?;
358 let key = asn1_encode_octet(&self.issuer_key_hash)?;
359 let sn = asn1_encode_integer(&self.serial_num)?;
360 oid.extend(name);
361 oid.extend(key);
362 oid.extend(sn);
363 let len = asn1_encode_length(oid.len())?;
364 let mut tlv = vec![ASN1_SEQUENCE];
365 tlv.extend(len);
366 tlv.extend(oid);
367
368 trace!("Cid {:?} successfully encoded", self);
369 Ok(tlv)
370 }
371}
372#[cfg(test)]
373mod test {
374 use hex::FromHex;
375
376 use crate::oid::{ALGO_SHA1_DOT, OCSP_EXT_CRL_REASON_DOT, OCSP_EXT_CRL_REASON_ID};
377
378 use super::*;
379
380 #[test]
382 fn encoding_length_over128() {
383 let v = asn1_encode_length(4934).unwrap();
384 let c = vec![0x82, 0x13, 0x46u8];
385 assert_eq!(c, v);
386
387 let v = asn1_encode_length(256).unwrap();
388 let c = vec![0x82, 0x01, 0x00u8];
389 assert_eq!(c, v);
390 }
391
392 #[test]
394 fn encoding_length_under128() {
395 let v = asn1_encode_length(52).unwrap();
396 let c = vec![0x34u8];
397 assert_eq!(c, v);
398
399 let v = asn1_encode_length(127).unwrap();
400 let c = vec![0x7fu8];
401 assert_eq!(c, v);
402 }
403
404 #[test]
406 fn encode_bit_string() {
407 let sign = vec![
408 0x6du8, 0xdb, 0x51, 0x4f, 0x2c, 0x6a, 0x35, 0x49, 0x80, 0x1e, 0x40, 0x1e, 0x31, 0x45,
409 0xdd, 0x88, 0x4a, 0x6a, 0x47, 0x2c, 0x8a, 0x09, 0xa6, 0xf9, 0xa3, 0x18, 0x79, 0x85,
410 0xa3, 0x4e, 0xcb, 0x59, 0xa2, 0xbb, 0x49, 0x15, 0x40, 0x9b, 0x8d, 0x89, 0x25, 0x05,
411 0x5d, 0xa0, 0x6a, 0xb3, 0xb1, 0x07, 0x57, 0xde, 0x46, 0x43, 0x37, 0xd7, 0x0b, 0x29,
412 0x56, 0x67, 0xf9, 0x7a, 0xbb, 0x33, 0x78, 0x3d, 0x5f, 0x38, 0x5a, 0xb8, 0x77, 0x38,
413 0x1b, 0xac, 0x7c, 0x15, 0xdb, 0xcf, 0x85, 0xe9, 0x38, 0x51, 0x94, 0x39, 0x7d, 0x05,
414 0x34, 0x2e, 0x32, 0x64, 0xb7, 0x72, 0x49, 0x51, 0xbd, 0x61, 0xf6, 0x8c, 0x0b, 0x7f,
415 0xa1, 0x02, 0x97, 0xa2, 0xe0, 0x41, 0x35, 0xdc, 0xe5, 0x5c, 0x55, 0x74, 0xab, 0x02,
416 0xcf, 0x63, 0x76, 0x96, 0x98, 0xa6, 0xec, 0x0d, 0x94, 0xa3, 0xa2, 0xf5, 0xbe, 0xee,
417 0x0a, 0xdd, 0x0f, 0x5d, 0x9e, 0x96, 0x7a, 0x73, 0x6d, 0xb7, 0x45, 0xbd, 0xda, 0xa7,
418 0x90, 0xf7, 0x49, 0x16, 0x0f, 0x42, 0xf1, 0x03, 0x70, 0x3f, 0xec, 0xb4, 0xa8, 0x09,
419 0x55, 0xa0, 0x5c, 0x7a, 0x7a, 0x29, 0xac, 0xf6, 0x13, 0xd8, 0xac, 0x08, 0x15, 0x5c,
420 0xab, 0x2f, 0x59, 0xc0, 0xc3, 0xe3, 0x3d, 0x2d, 0x1b, 0xb0, 0x56, 0x0a, 0xde, 0x03,
421 0x94, 0x30, 0x86, 0xdf, 0x7d, 0xa7, 0x48, 0x4a, 0x8c, 0x7b, 0x6d, 0xca, 0x10, 0x79,
422 0x6d, 0x42, 0x69, 0x79, 0xbd, 0x02, 0x1d, 0x22, 0x00, 0x94, 0x98, 0x5f, 0x94, 0x89,
423 0x0b, 0xca, 0xdc, 0x03, 0x54, 0xb2, 0x89, 0x93, 0x1f, 0xf4, 0x56, 0x4c, 0x98, 0xdf,
424 0xf8, 0xe5, 0x32, 0x69, 0x5d, 0x21, 0xc8, 0x2f, 0x46, 0x18, 0xfd, 0x60, 0x98, 0x7d,
425 0x98, 0xee, 0x04, 0x09, 0xfb, 0xa4, 0x8a, 0xe4, 0x46, 0xdf, 0xfe, 0xc7, 0x1d, 0xb9,
426 0x57, 0x40, 0x69, 0xb4,
427 ];
428
429 let bit = asn1_encode_bit_string(&sign).unwrap();
430 let c = vec![
431 0x03, 0x82, 0x01, 0x00, 0x6d, 0xdb, 0x51, 0x4f, 0x2c, 0x6a, 0x35, 0x49, 0x80, 0x1e,
432 0x40, 0x1e, 0x31, 0x45, 0xdd, 0x88, 0x4a, 0x6a, 0x47, 0x2c, 0x8a, 0x09, 0xa6, 0xf9,
433 0xa3, 0x18, 0x79, 0x85, 0xa3, 0x4e, 0xcb, 0x59, 0xa2, 0xbb, 0x49, 0x15, 0x40, 0x9b,
434 0x8d, 0x89, 0x25, 0x05, 0x5d, 0xa0, 0x6a, 0xb3, 0xb1, 0x07, 0x57, 0xde, 0x46, 0x43,
435 0x37, 0xd7, 0x0b, 0x29, 0x56, 0x67, 0xf9, 0x7a, 0xbb, 0x33, 0x78, 0x3d, 0x5f, 0x38,
436 0x5a, 0xb8, 0x77, 0x38, 0x1b, 0xac, 0x7c, 0x15, 0xdb, 0xcf, 0x85, 0xe9, 0x38, 0x51,
437 0x94, 0x39, 0x7d, 0x05, 0x34, 0x2e, 0x32, 0x64, 0xb7, 0x72, 0x49, 0x51, 0xbd, 0x61,
438 0xf6, 0x8c, 0x0b, 0x7f, 0xa1, 0x02, 0x97, 0xa2, 0xe0, 0x41, 0x35, 0xdc, 0xe5, 0x5c,
439 0x55, 0x74, 0xab, 0x02, 0xcf, 0x63, 0x76, 0x96, 0x98, 0xa6, 0xec, 0x0d, 0x94, 0xa3,
440 0xa2, 0xf5, 0xbe, 0xee, 0x0a, 0xdd, 0x0f, 0x5d, 0x9e, 0x96, 0x7a, 0x73, 0x6d, 0xb7,
441 0x45, 0xbd, 0xda, 0xa7, 0x90, 0xf7, 0x49, 0x16, 0x0f, 0x42, 0xf1, 0x03, 0x70, 0x3f,
442 0xec, 0xb4, 0xa8, 0x09, 0x55, 0xa0, 0x5c, 0x7a, 0x7a, 0x29, 0xac, 0xf6, 0x13, 0xd8,
443 0xac, 0x08, 0x15, 0x5c, 0xab, 0x2f, 0x59, 0xc0, 0xc3, 0xe3, 0x3d, 0x2d, 0x1b, 0xb0,
444 0x56, 0x0a, 0xde, 0x03, 0x94, 0x30, 0x86, 0xdf, 0x7d, 0xa7, 0x48, 0x4a, 0x8c, 0x7b,
445 0x6d, 0xca, 0x10, 0x79, 0x6d, 0x42, 0x69, 0x79, 0xbd, 0x02, 0x1d, 0x22, 0x00, 0x94,
446 0x98, 0x5f, 0x94, 0x89, 0x0b, 0xca, 0xdc, 0x03, 0x54, 0xb2, 0x89, 0x93, 0x1f, 0xf4,
447 0x56, 0x4c, 0x98, 0xdf, 0xf8, 0xe5, 0x32, 0x69, 0x5d, 0x21, 0xc8, 0x2f, 0x46, 0x18,
448 0xfd, 0x60, 0x98, 0x7d, 0x98, 0xee, 0x04, 0x09, 0xfb, 0xa4, 0x8a, 0xe4, 0x46, 0xdf,
449 0xfe, 0xc7, 0x1d, 0xb9, 0x57, 0x40, 0x69, 0xb4,
450 ];
451
452 assert_eq!(c, bit);
453 }
454
455 #[test]
457 fn certid_to_der() {
458 let oid = Oid::new_from_dot(ALGO_SHA1_DOT).unwrap();
459 let name = vec![
460 0x69, 0x4d, 0x18, 0xa9, 0xbe, 0x42, 0xf7, 0x80, 0x26, 0x14, 0xd4, 0x84, 0x4f, 0x23,
461 0x60, 0x14, 0x78, 0xb7, 0x88, 0x20,
462 ];
463 let key = vec![
464 0x39, 0x7b, 0xe0, 0x02, 0xa2, 0xf5, 0x71, 0xfd, 0x80, 0xdc, 0xeb, 0x52, 0xa1, 0x7a,
465 0x7f, 0x8b, 0x63, 0x2b, 0xe7, 0x55,
466 ];
467 let sn = vec![0x41, 0x30, 0x09, 0x83, 0x33, 0x1f, 0x9d, 0x4f];
468 let certid = CertId::new(oid, &name, &key, &sn);
469 let v = certid.to_der().unwrap();
470 let c = vec![
471 0x30, 0x41, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04,
472 0x14, 0x69, 0x4d, 0x18, 0xa9, 0xbe, 0x42, 0xf7, 0x80, 0x26, 0x14, 0xd4, 0x84, 0x4f,
473 0x23, 0x60, 0x14, 0x78, 0xb7, 0x88, 0x20, 0x04, 0x14, 0x39, 0x7b, 0xe0, 0x02, 0xa2,
474 0xf5, 0x71, 0xfd, 0x80, 0xdc, 0xeb, 0x52, 0xa1, 0x7a, 0x7f, 0x8b, 0x63, 0x2b, 0xe7,
475 0x55, 0x02, 0x08, 0x41, 0x30, 0x09, 0x83, 0x33, 0x1f, 0x9d, 0x4f,
476 ];
477
478 assert_eq!(c, v);
479 }
480
481 #[test]
483 fn oid_to_der() {
484 let oid = Oid::new_from_dot(ALGO_SHA1_DOT).unwrap();
485 let v = oid.to_der_with_null().unwrap();
486 assert_eq!(
487 vec![0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00],
488 v
489 );
490 }
491
492 #[test]
494 fn oid_dot_new() {
495 let dot = OCSP_EXT_CRL_REASON_DOT;
496 let d = Oid::new_from_dot(dot).unwrap().index;
497 assert_eq!(d, OCSP_EXT_CRL_REASON_ID);
498 }
499
500 #[test]
502 fn generalized_time_to_der_utc() {
503 let gt = GeneralizedTime {
504 year: 2021,
505 month: 1,
506 day: 13,
507 hour: 3,
508 min: 9,
509 sec: 25,
510 };
511
512 let der = gt.to_der_utc().unwrap();
513 assert_eq!(
514 vec![
515 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, 0x33, 0x30, 0x33, 0x30, 0x39,
516 0x32, 0x35, 0x5a
517 ],
518 der
519 );
520 }
521
522 #[test]
524 fn asn1_length_4934() {
525 let v = asn1_encode_length(4934).unwrap();
526 assert_eq!(vec![0x82, 0x13, 0x46], v);
527 }
528
529 #[test]
531 fn asn1_length_127() {
532 let v = asn1_encode_length(52).unwrap();
533 assert_eq!(vec![0x34], v)
534 }
535
536 #[test]
538 fn num2hex() {
539 let num: u32 = 2021;
540 let hex = num.to_string();
541 let hex = hex.as_bytes();
542 assert_eq!(vec![0x32, 0x30, 0x32, 0x31], hex);
543 }
544
545 #[test]
547 fn hex2time() {
548 let hex = "32303231303131333033303932355a";
549 let hex = Vec::from_hex(hex).unwrap();
550 let time = std::str::from_utf8(&hex).unwrap();
551 assert_eq!("20210113030925Z", time);
552 }
553}