1#![allow(unused)]
2
3use std::io::{Bytes, Read};
4
5use crate::util::der::{DerClass, DerError, DerType};
6use crate::util::oid::ObjectIdentifier;
7
8struct DerStackItem {
9 len: Option<usize>,
10 parsed_len: usize,
11}
12
13pub struct DerReader<R: Read> {
14 input: Bytes<R>,
15 stack: Vec<DerStackItem>,
16 der_type: DerType,
17 constructed: bool,
18 contents: Option<Vec<u8>>,
19 read_count: usize,
20}
21
22impl<'a> DerReader<&'a [u8]> {
23 pub fn from_bytes(input: &'a impl AsRef<[u8]>) -> Self {
24 Self::from_reader(input.as_ref())
25 }
26}
27
28impl<R: Read> DerReader<R> {
29 pub fn from_reader(input: R) -> Self {
30 Self {
31 input: input.bytes(),
32 stack: Vec::new(),
33 der_type: DerType::EndOfContents,
34 constructed: false,
35 contents: None,
36 read_count: 0,
37 }
38 }
39
40 pub fn next(&mut self) -> Result<Option<DerType>, DerError> {
41 let mut depth = self.stack.len();
42 let mut is_indefinite_parent = false;
43 if depth > 0 {
44 match self.stack[depth - 1].len {
45 Some(val) => {
46 if val == self.stack[depth - 1].parsed_len {
47 self.stack.pop();
48
49 depth = self.stack.len();
50 if depth > 0 {
51 self.stack[depth - 1].parsed_len += val;
52 }
53
54 return Ok(Some(DerType::EndOfContents));
55 }
56 }
57 None => {
58 is_indefinite_parent = true;
59 }
60 }
61 }
62
63 let start_read_count = self.read_count;
64
65 match self.get_tag()? {
66 None => return Ok(None),
67 Some((DerType::EndOfContents, constructed)) => {
68 if !is_indefinite_parent {
69 return Err(DerError::InvalidTag(format!(
70 "End of contents type is not allowed here."
71 )));
72 }
73
74 if constructed {
75 return Err(DerError::InvalidTag(format!(
76 "End of contents type cannot be constructed."
77 )));
78 }
79
80 match self.get_length()? {
81 Some(0) => {}
82 Some(val) => {
83 return Err(DerError::InvalidLength(format!(
84 "End of contents content length must be 0: {}",
85 val
86 )));
87 }
88 None => {
89 return Err(DerError::InvalidLength(format!(
90 "End of contents content length must be 0: indefinite"
91 )));
92 }
93 }
94
95 self.stack.pop();
96
97 self.der_type = DerType::EndOfContents;
98 self.constructed = constructed;
99 self.contents = None;
100 }
101 Some((der_type, true)) => {
102 if !der_type.can_constructed() {
103 return Err(DerError::InvalidTag(format!(
104 "{} type cannot be constructed.",
105 der_type
106 )));
107 }
108
109 let olength = self.get_length()?;
110 let offset = self.read_count - start_read_count;
111 self.stack.push(DerStackItem {
112 len: olength.map(|val| val + offset),
113 parsed_len: offset,
114 });
115
116 self.der_type = der_type;
117 self.constructed = true;
118 self.contents = None;
119 }
120 Some((der_type, false)) => {
121 if !der_type.can_primitive() {
122 return Err(DerError::InvalidTag(format!(
123 "{} type cannot be primitive.",
124 der_type
125 )));
126 }
127
128 let length = match self.get_length()? {
129 Some(val) => val,
130 None => {
131 return Err(DerError::InvalidLength(format!(
132 "Primitive type content length cannot be indefinite."
133 )));
134 }
135 };
136
137 let mut contents = Vec::with_capacity(length);
138 for _ in 0..length {
139 match self.get()? {
140 Some(val) => contents.push(val),
141 None => return Err(DerError::UnexpectedEndOfInput),
142 }
143 }
144
145 if depth > 0 {
146 let offset = self.read_count - start_read_count;
147 self.stack[depth - 1].parsed_len += offset;
148 }
149
150 self.der_type = der_type;
151 self.constructed = false;
152 self.contents = Some(contents);
153 }
154 }
155
156 Ok(Some(self.der_type))
157 }
158
159 pub fn skip_contents(&mut self) -> Result<(), DerError> {
160 if self.constructed {
161 let mut depth = 1;
162 loop {
163 match self.next()? {
164 Some(DerType::EndOfContents) => {
165 depth -= 1;
166 if depth == 0 {
167 break;
168 }
169 }
170 Some(_) => {
171 if self.constructed {
172 depth += 1;
173 }
174 }
175 None => break,
176 }
177 }
178 }
179
180 Ok(())
181 }
182
183 pub fn is_constructed(&self) -> bool {
184 self.constructed
185 }
186
187 pub fn is_primitive(&self) -> bool {
188 !self.constructed
189 }
190
191 pub fn contents(&self) -> Option<&[u8]> {
192 match &self.contents {
193 Some(val) => Some(val),
194 None => None,
195 }
196 }
197
198 pub fn to_null(&self) -> Result<(), DerError> {
199 if let DerType::Null = self.der_type {
200 if let Some(contents) = &self.contents {
201 if contents.len() != 0 {
202 return Err(DerError::InvalidLength(format!(
203 "Null content length must be 0: {}",
204 contents.len()
205 )));
206 }
207
208 Ok(())
209 } else {
210 unreachable!();
211 }
212 } else {
213 panic!(
214 "{} type is not supported to convert to null.",
215 self.der_type
216 );
217 }
218 }
219
220 pub fn to_boolean(&self) -> Result<bool, DerError> {
221 if let DerType::Boolean = self.der_type {
222 if let Some(contents) = &self.contents {
223 if contents.len() != 1 {
224 return Err(DerError::InvalidLength(format!(
225 "Boolean content length must be 1: {}",
226 contents.len()
227 )));
228 }
229
230 let value = contents[0] != 0;
231 Ok(value)
232 } else {
233 unreachable!();
234 }
235 } else {
236 panic!(
237 "{} type is not supported to convert to bool.",
238 self.der_type
239 );
240 }
241 }
242
243 pub fn to_u8(&self) -> Result<u8, DerError> {
244 if let DerType::Integer | DerType::Enumerated = self.der_type {
245 if let Some(contents) = &self.contents {
246 if contents.len() == 0 {
247 return Err(DerError::InvalidLength(format!(
248 "{} content length must be 1 or more.",
249 self.der_type
250 )));
251 }
252
253 if contents.len() > 1 {
254 return Err(DerError::Overflow);
255 }
256
257 Ok(contents[0])
258 } else {
259 unreachable!();
260 }
261 } else {
262 panic!("{} type is not supported to convert to u8.", self.der_type);
263 }
264 }
265
266 pub fn to_u64(&self) -> Result<u64, DerError> {
267 if let DerType::Integer | DerType::Enumerated = self.der_type {
268 if let Some(contents) = &self.contents {
269 if contents.len() == 0 {
270 return Err(DerError::InvalidLength(format!(
271 "{} content length must be 1 or more.",
272 self.der_type
273 )));
274 }
275
276 let mut value = 0u64;
277 let mut shift_count = 0u8;
278 for i in 0..contents.len() {
279 let b = contents[i];
280 shift_count += 8;
281 if shift_count > 64 {
282 return Err(DerError::Overflow);
283 }
284 value = (value << 8) | b as u64;
285 }
286 Ok(value)
287 } else {
288 unreachable!();
289 }
290 } else {
291 panic!("{} type is not supported to convert to u64.", self.der_type);
292 }
293 }
294
295 pub fn to_be_bytes(&self, sign: bool, min_len: usize) -> Vec<u8> {
296 if let DerType::Integer = self.der_type {
297 if let Some(contents) = &self.contents {
298 if contents.len() < min_len {
299 let mut vec = Vec::with_capacity(min_len);
300 if sign && contents.len() > 0 && (contents[0] & 0b10000000) != 0 {
301 vec.push(0b10000000);
302 for _ in 0..(min_len - contents.len() - 1) {
303 vec.push(0);
304 }
305 vec.push(contents[0] & 0b01111111);
306 vec.extend_from_slice(&contents[1..]);
307 } else {
308 for _ in 0..(min_len - contents.len()) {
309 vec.push(0);
310 }
311 vec.extend_from_slice(contents);
312 }
313 vec
314 } else if contents.len() - 1 >= min_len
315 && !sign
316 && contents.len() > 0
317 && contents[0] == 0
318 {
319 contents[1..].to_vec()
320 } else {
321 contents.to_vec()
322 }
323 } else {
324 unreachable!();
325 }
326 } else {
327 panic!(
328 "{} type is not supported to convert to BitVec",
329 self.der_type
330 );
331 }
332 }
333
334 pub fn to_vec(&self) -> Result<Vec<u8>, DerError> {
335 if let DerType::OctetString = self.der_type {
336 if let Some(contents) = &self.contents {
337 Ok(contents.to_vec())
338 } else {
339 unreachable!();
340 }
341 } else {
342 panic!(
343 "{} type is not supported to convert to OctetString",
344 self.der_type
345 );
346 }
347 }
348
349 pub fn to_bit_vec(&self) -> Result<(Vec<u8>, u8), DerError> {
350 if let DerType::BitString = self.der_type {
351 if let Some(contents) = &self.contents {
352 if contents.len() < 2 {
353 return Err(DerError::InvalidLength(format!(
354 "Bit String content length must be 2 or more."
355 )));
356 }
357
358 let unused_bits = contents[0];
359 if unused_bits > 7 {
360 return Err(DerError::InvalidContents(format!(
361 "Unused bit count of Bit String must be from 0 to 7."
362 )));
363 }
364
365 Ok((contents[1..contents.len()].to_vec(), unused_bits))
366 } else {
367 unreachable!();
368 }
369 } else {
370 panic!(
371 "{} type is not supported to convert to BitVec",
372 self.der_type
373 );
374 }
375 }
376
377 pub fn to_string(&self) -> Result<String, DerError> {
378 if let DerType::Utf8String = self.der_type {
379 if let Some(contents) = &self.contents {
380 let value = String::from_utf8(contents.to_vec()).map_err(|_| {
381 DerError::InvalidContents("Invalid UTF-8 sequence found".to_string())
382 })?;
383 Ok(value)
384 } else {
385 unreachable!();
386 }
387 } else {
388 panic!(
389 "{} type is not supported to convert to String.",
390 self.der_type
391 );
392 }
393 }
394
395 pub fn to_object_identifier(&self) -> Result<ObjectIdentifier, DerError> {
396 if let DerType::ObjectIdentifier = self.der_type {
397 if let Some(contents) = &self.contents {
398 let mut oid = Vec::<u64>::new();
399 if contents.len() > 0 {
400 let b0 = contents[0];
401 oid.push((b0 / 40) as u64);
402 oid.push((b0 % 40) as u64);
403
404 let mut buf = 0u64;
405 let mut shift_count = 0u8;
406 for i in 1..contents.len() {
407 let b = contents[i];
408 shift_count += 7;
409 if shift_count > 64 {
410 return Err(DerError::Overflow);
411 }
412 buf = (buf << 7) | (b & 0x7F) as u64;
413 if b & 0x80 == 0 {
414 oid.push(buf);
415 buf = 0u64;
416 shift_count = 0;
417 }
418 }
419 }
420 return Ok(ObjectIdentifier::from_slice(&oid));
421 } else {
422 unreachable!();
423 }
424 }
425 panic!(
426 "{} type is not supported to convert to ObjectIdentifier.",
427 self.der_type
428 );
429 }
430
431 fn get_tag(&mut self) -> Result<Option<(DerType, bool)>, DerError> {
432 let result = match self.get()? {
433 Some(val) => {
434 let der_class = Self::lookup_der_class(val >> 6);
435 let constructed = ((val >> 5) & 0x01) != 0;
436 let tag_no = if (val & 0x1F) > 30 {
437 let mut buf = 0u64;
438 let mut shift_count = 0u8;
439 loop {
440 match self.get()? {
441 Some(val) => {
442 shift_count += 7;
443 if shift_count > 64 {
444 return Err(DerError::Overflow);
445 }
446 buf = (buf << 7) | (val & 0x7F) as u64;
447 if val & 0x80 == 0 {
448 break;
449 }
450 }
451 None => return Err(DerError::UnexpectedEndOfInput),
452 }
453 }
454 buf
455 } else {
456 (val & 0x1F) as u64
457 };
458
459 Some((Self::lookup_der_type(der_class, tag_no), constructed))
460 }
461 None => None,
462 };
463 Ok(result)
464 }
465
466 fn lookup_der_class(class_no: u8) -> DerClass {
467 match class_no {
468 0b00 => DerClass::Universal,
469 0b01 => DerClass::Application,
470 0b10 => DerClass::ContextSpecific,
471 0b11 => DerClass::Private,
472 _ => unreachable!(),
473 }
474 }
475
476 fn lookup_der_type(class: DerClass, tag_no: u64) -> DerType {
477 match (class, tag_no) {
478 (DerClass::Universal, 0) => DerType::EndOfContents,
479 (DerClass::Universal, 1) => DerType::Boolean,
480 (DerClass::Universal, 2) => DerType::Integer,
481 (DerClass::Universal, 3) => DerType::BitString,
482 (DerClass::Universal, 4) => DerType::OctetString,
483 (DerClass::Universal, 5) => DerType::Null,
484 (DerClass::Universal, 6) => DerType::ObjectIdentifier,
485 (DerClass::Universal, 7) => DerType::ObjectDescriptor,
486 (DerClass::Universal, 8) => DerType::External,
487 (DerClass::Universal, 9) => DerType::Real,
488 (DerClass::Universal, 10) => DerType::Enumerated,
489 (DerClass::Universal, 11) => DerType::EmbeddedPdv,
490 (DerClass::Universal, 12) => DerType::Utf8String,
491 (DerClass::Universal, 13) => DerType::RelativeOid,
492 (DerClass::Universal, 14) => DerType::Time,
493 (DerClass::Universal, 16) => DerType::Sequence,
494 (DerClass::Universal, 17) => DerType::Set,
495 (DerClass::Universal, 18) => DerType::NumericString,
496 (DerClass::Universal, 19) => DerType::PrintableString,
497 (DerClass::Universal, 20) => DerType::TeletexString,
498 (DerClass::Universal, 21) => DerType::VideotexString,
499 (DerClass::Universal, 22) => DerType::Ia5String,
500 (DerClass::Universal, 23) => DerType::UtcTime,
501 (DerClass::Universal, 24) => DerType::GeneralizedTime,
502 (DerClass::Universal, 25) => DerType::GraphicString,
503 (DerClass::Universal, 26) => DerType::VisibleString,
504 (DerClass::Universal, 27) => DerType::GeneralString,
505 (DerClass::Universal, 28) => DerType::UniversalString,
506 (DerClass::Universal, 29) => DerType::CharacterString,
507 (DerClass::Universal, 30) => DerType::BmpString,
508 (DerClass::Universal, 31) => DerType::Date,
509 (DerClass::Universal, 32) => DerType::TimeOfDay,
510 (DerClass::Universal, 33) => DerType::DateTime,
511 (DerClass::Universal, 34) => DerType::Duration,
512 _ => DerType::Other(class, tag_no),
513 }
514 }
515
516 fn get_length(&mut self) -> Result<Option<usize>, DerError> {
517 let result = match self.get()? {
518 Some(val) if val == 0xFF => {
519 return Err(DerError::InvalidLength(format!(
520 "Length 0x{:X} is reserved for possible future extension.",
521 val
522 )));
523 }
524 Some(val) if val == 0x80 => None,
525 Some(val) if val < 0x80 => Some(val as usize),
526 Some(val) => {
527 let len_size = (val & 0x7F) as usize;
528 if len_size > std::mem::size_of::<usize>() {
529 return Err(DerError::Overflow);
530 }
531 let mut num = 0usize;
532 for _ in 0..len_size {
533 match self.get()? {
534 Some(val) => {
535 num = num << 8 | val as usize;
536 }
537 None => return Err(DerError::UnexpectedEndOfInput),
538 }
539 }
540 Some(num)
541 }
542 None => return Err(DerError::UnexpectedEndOfInput),
543 };
544 Ok(result)
545 }
546
547 fn get(&mut self) -> Result<Option<u8>, DerError> {
548 let result = match self.input.next() {
549 Some(Ok(val)) => {
550 self.read_count += 1;
551 Some(val)
552 }
553 Some(Err(err)) => return Err(DerError::ReadFailure(err)),
554 None => None,
555 };
556 Ok(result)
557 }
558}
559
560#[cfg(test)]
561mod tests {
562 use super::*;
563
564 use anyhow::Result;
565 use std::fs::File;
566 use std::path::PathBuf;
567
568 use crate::util::der::DerBuilder;
569
570 #[test]
571 fn parse_der() -> Result<()> {
572 let bytes = load_file("der/RSA_2048bit_raw_public.der")?;
573
574 let mut parser = DerReader::from_reader(bytes);
575 assert!(matches!(parser.next()?, Some(DerType::Sequence)));
576 assert!(matches!(parser.next()?, Some(DerType::Integer)));
577 assert!(matches!(parser.next()?, Some(DerType::Integer)));
578 assert!(matches!(parser.next()?, Some(DerType::EndOfContents)));
579 Ok(())
580 }
581
582 #[test]
583 fn parse_der_2() -> Result<()> {
584 let mut vec = Vec::new();
585 let _ = load_file("der/RSA_2048bit_raw_public.der")?.read_to_end(&mut vec)?;
586
587 let mut parser = DerReader::from_bytes(&vec);
588 assert!(matches!(parser.next()?, Some(DerType::Sequence)));
589 assert!(matches!(parser.next()?, Some(DerType::Integer)));
590 assert!(matches!(parser.next()?, Some(DerType::Integer)));
591 assert!(matches!(parser.next()?, Some(DerType::EndOfContents)));
592 Ok(())
593 }
594
595 #[test]
596 fn parse_der_3() -> Result<()> {
597 let mut builder = DerBuilder::new();
598 builder.begin(DerType::Sequence);
599 {
600 builder.begin(DerType::Sequence);
601 {
602 builder.append_integer_from_u8(1);
603 }
604 builder.end();
605 }
606 builder.end();
607
608 let input = builder.build();
609 let mut parser = DerReader::from_bytes(&input);
610 assert!(matches!(parser.next()?, Some(DerType::Sequence)));
611 assert!(matches!(parser.next()?, Some(DerType::Sequence)));
612 assert!(matches!(parser.next()?, Some(DerType::Integer)));
613 assert!(matches!(parser.next()?, Some(DerType::EndOfContents)));
614 assert!(matches!(parser.next()?, Some(DerType::EndOfContents)));
615
616 Ok(())
617 }
618
619 fn load_file(path: &str) -> Result<File> {
620 let mut pb = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
621 pb.push("data");
622 pb.push(path);
623
624 let file = File::open(&pb)?;
625 Ok(file)
626 }
627}