Skip to main content

tsumiki_der/
lib.rs

1//! # tsumiki-der
2//!
3//! DER (Distinguished Encoding Rules) parsing and encoding.
4//!
5//! This crate implements DER encoding as defined in
6//! [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690).
7//!
8//! ## What is DER?
9//!
10//! DER is a binary encoding format for ASN.1 data structures. It uses a
11//! Tag-Length-Value (TLV) structure where:
12//! - **Tag**: Identifies the data type (INTEGER, SEQUENCE, etc.)
13//! - **Length**: The size of the value in bytes
14//! - **Value**: The actual data
15//!
16//! ## Example
17//!
18//! ```
19//! use tsumiki::decoder::Decoder;
20//! use tsumiki_der::Der;
21//!
22//! // DER-encoded SEQUENCE with one INTEGER (value 42)
23//! let bytes = vec![0x30, 0x03, 0x02, 0x01, 0x2a];
24//!
25//! // Parse DER
26//! let der: Der = bytes.decode()?;
27//!
28//! assert_eq!(der.elements().len(), 1);
29//! # Ok::<(), Box<dyn std::error::Error>>(())
30//! ```
31//!
32//! ## Encoding
33//!
34//! ```
35//! use tsumiki::encoder::Encoder;
36//! use tsumiki_der::{Der, Tlv, Tag, PrimitiveTag};
37//!
38//! // Create DER structure
39//! let tlv = Tlv::new_primitive(Tag::Primitive(PrimitiveTag::Integer, 0x02), vec![0x2a]);
40//! let der = Der::new(vec![tlv]);
41//!
42//! // Encode to bytes
43//! let bytes: Vec<u8> = der.encode()?;
44//! # Ok::<(), Box<dyn std::error::Error>>(())
45//! ```
46
47#![forbid(unsafe_code)]
48
49use error::Error;
50use nom::{IResult, Parser};
51use tsumiki::decoder::{DecodableFrom, Decoder};
52use tsumiki::encoder::{EncodableTo, Encoder};
53use tsumiki_pem::Pem;
54
55pub mod error;
56
57/// Represents a DER (Distinguished Encoding Rules) encoded structure.
58///
59/// A DER structure consists of one or more TLV (Tag-Length-Value) elements.
60/// DER is a binary encoding format for ASN.1 data structures, commonly used
61/// in cryptographic standards like X.509 certificates and PKCS formats.
62///
63/// Defined in [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690) Section 8.
64///
65/// # Example
66///
67/// ```
68/// use tsumiki::decoder::Decoder;
69/// use tsumiki_der::Der;
70///
71/// // DER-encoded INTEGER with value 42
72/// let bytes = vec![0x02, 0x01, 0x2a];
73/// let der: Der = bytes.decode()?;
74/// # Ok::<(), Box<dyn std::error::Error>>(())
75/// ```
76#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct Der {
78    elements: Vec<Tlv>,
79}
80
81impl Der {
82    /// Returns a slice of TLV elements in this DER structure.
83    pub fn elements(&self) -> &[Tlv] {
84        &self.elements
85    }
86
87    /// Creates a new DER structure from a vector of TLV elements.
88    ///
89    /// # Example
90    ///
91    /// ```
92    /// use tsumiki_der::{Der, Tlv, Tag, PrimitiveTag};
93    ///
94    /// let tlv = Tlv::new_primitive(Tag::Primitive(PrimitiveTag::Integer, 0x02), vec![0x2a]);
95    /// let der = Der::new(vec![tlv]);
96    /// ```
97    pub fn new(elements: Vec<Tlv>) -> Self {
98        Der { elements }
99    }
100}
101
102impl EncodableTo<Der> for Vec<u8> {}
103
104impl Encoder<Der, Vec<u8>> for Der {
105    type Error = Error;
106
107    fn encode(&self) -> Result<Vec<u8>, Self::Error> {
108        self.elements
109            .iter()
110            .map(|tlv| tlv.encode())
111            .collect::<Result<Vec<_>, _>>()
112            .map(|vecs| vecs.into_iter().flatten().collect())
113    }
114}
115
116impl DecodableFrom<Vec<u8>> for Der {}
117
118impl Decoder<Vec<u8>, Der> for Vec<u8> {
119    type Error = Error;
120
121    fn decode(&self) -> Result<Der, Self::Error> {
122        let mut tlvs = Vec::new();
123        let mut input = self.as_slice();
124        while !input.is_empty() {
125            let (new_input, tlv) = Tlv::parse(input).map_err(|e| match e {
126                nom::Err::Error(e) => Error::Parser(e.code),
127                nom::Err::Incomplete(e) => Error::ParserIncomplete(e),
128                nom::Err::Failure(e) => Error::Parser(e.code),
129            })?;
130            input = new_input;
131            tlvs.push(tlv);
132        }
133        Ok(Der { elements: tlvs })
134    }
135}
136
137impl DecodableFrom<&[u8]> for Der {}
138
139impl Decoder<&[u8], Der> for &[u8] {
140    type Error = Error;
141
142    fn decode(&self) -> Result<Der, Self::Error> {
143        let mut tlvs = Vec::new();
144        let mut input = *self;
145        while !input.is_empty() {
146            let (new_input, tlv) = Tlv::parse(input).map_err(|e| match e {
147                nom::Err::Error(e) => Error::Parser(e.code),
148                nom::Err::Incomplete(e) => Error::ParserIncomplete(e),
149                nom::Err::Failure(e) => Error::Parser(e.code),
150            })?;
151            input = new_input;
152            tlvs.push(tlv);
153        }
154        Ok(Der { elements: tlvs })
155    }
156}
157
158impl DecodableFrom<Pem> for Der {}
159
160impl Decoder<Pem, Der> for Pem {
161    type Error = Error;
162
163    fn decode(&self) -> Result<Der, Self::Error> {
164        // TODO: consider better syntax
165        let data = Decoder::<Pem, Vec<u8>>::decode(self).map_err(Error::Pem)?;
166        data.decode()
167    }
168}
169
170/// Tag byte constructed flag (bit 5).
171///
172/// This bit is set in the tag byte to indicate that the TLV contains constructed
173/// data (i.e., nested TLVs) rather than primitive data.
174pub const TAG_CONSTRUCTED: u8 = 0b0010_0000;
175
176/// Represents a DER tag that identifies the type of data in a TLV structure.
177///
178/// Tags can be either primitive ASN.1 types (INTEGER, SEQUENCE, etc.) or
179/// context-specific tags used in structured data like X.509 extensions.
180///
181/// # Example
182///
183/// ```
184/// use tsumiki_der::{Tag, PrimitiveTag};
185///
186/// // Primitive tag for INTEGER
187/// let int_tag = Tag::Primitive(PrimitiveTag::Integer, 0x02);
188///
189/// // Context-specific tag [0] EXPLICIT
190/// let ctx_tag = Tag::ContextSpecific { slot: 0, constructed: true };
191/// ```
192#[derive(Debug, Clone, Copy, PartialEq, Eq)]
193pub enum Tag {
194    /// Primitive ASN.1 tag with the primitive type and raw tag byte.
195    Primitive(PrimitiveTag, u8),
196    /// Context-specific tag with slot number and constructed flag.
197    ContextSpecific { slot: u8, constructed: bool },
198}
199
200impl Tag {
201    /// Returns whether this tag represents constructed data.
202    ///
203    /// Constructed data contains nested TLV structures, while primitive data
204    /// contains raw bytes.
205    pub(crate) fn is_constructed(&self) -> bool {
206        match self {
207            Tag::Primitive(_, inner) => (*inner) & TAG_CONSTRUCTED != 0,
208            Tag::ContextSpecific { constructed, .. } => *constructed,
209        }
210    }
211}
212
213impl EncodableTo<Tag> for u8 {}
214
215impl Encoder<Tag, u8> for Tag {
216    type Error = Error;
217
218    fn encode(&self) -> Result<u8, Self::Error> {
219        Ok(match self {
220            Tag::Primitive(_, value) => *value,
221            Tag::ContextSpecific { slot, constructed } => {
222                let base = 0x80; // Context-specific class
223                let constructed_bit = if *constructed { TAG_CONSTRUCTED } else { 0 };
224                base | constructed_bit | slot
225            }
226        })
227    }
228}
229
230impl From<u8> for Tag {
231    fn from(value: u8) -> Self {
232        let is_context_specific = value & 0b1000_0000 != 0;
233
234        if is_context_specific {
235            // Context-specific tag
236            // Bit 5 indicates constructed (1) or primitive (0)
237            let constructed = value & TAG_CONSTRUCTED != 0;
238            let slot_number = value & 0b0001_1111; // Bits 0-4 are the slot number
239            Tag::ContextSpecific {
240                slot: slot_number,
241                constructed,
242            }
243        } else {
244            let primitive = PrimitiveTag::from(value & 0b0001_1111);
245            Tag::Primitive(primitive, value)
246        }
247    }
248}
249
250/// Primitive ASN.1 tag types.
251///
252/// These tags identify the data type in ASN.1 structures. The numeric values
253/// correspond to the standard ASN.1 universal tag numbers defined in
254/// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680) and encoded according to
255/// [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690).
256///
257/// # Example
258///
259/// ```
260/// use tsumiki_der::PrimitiveTag;
261///
262/// let tag = PrimitiveTag::Integer;
263/// assert_eq!(u8::from(&tag), 0x02);
264/// ```
265#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
266#[repr(u8)]
267pub enum PrimitiveTag {
268    /// BOOLEAN type (tag 0x01).
269    Boolean = 0x01,
270    /// INTEGER type (tag 0x02).
271    Integer = 0x02,
272    /// BIT STRING type (tag 0x03).
273    BitString = 0x03,
274    /// OCTET STRING type (tag 0x04).
275    OctetString = 0x04,
276    /// NULL type (tag 0x05).
277    Null = 0x05,
278    /// OBJECT IDENTIFIER type (tag 0x06).
279    ObjectIdentifier = 0x06,
280    /// UTF8String type (tag 0x0c).
281    UTF8String = 0x0c,
282    /// SEQUENCE and SEQUENCE OF type (tag 0x10).
283    Sequence = 0x10,
284    /// SET and SET OF type (tag 0x11).
285    Set = 0x11,
286    /// PrintableString type (tag 0x13).
287    PrintableString = 0x13,
288    /// IA5String type (tag 0x16).
289    IA5String = 0x16,
290    /// UTCTime type (tag 0x17).
291    UTCTime = 0x17,
292    /// GeneralizedTime type (tag 0x18).
293    GeneralizedTime = 0x18,
294    /// BMPString type (tag 0x1e).
295    BMPString = 0x1e,
296    /// Unimplemented or unknown tag type.
297    Unimplemented(u8),
298}
299
300impl From<u8> for PrimitiveTag {
301    fn from(value: u8) -> Self {
302        match value {
303            0x01 => Self::Boolean,
304            0x02 => Self::Integer,
305            0x03 => Self::BitString,
306            0x04 => Self::OctetString,
307            0x05 => Self::Null,
308            0x06 => Self::ObjectIdentifier,
309            0x0c => Self::UTF8String,
310            0x10 => Self::Sequence,
311            0x11 => Self::Set,
312            0x13 => Self::PrintableString,
313            0x16 => Self::IA5String,
314            0x17 => Self::UTCTime,
315            0x18 => Self::GeneralizedTime,
316            0x1e => Self::BMPString,
317            _ => PrimitiveTag::Unimplemented(value),
318        }
319    }
320}
321
322impl From<&PrimitiveTag> for u8 {
323    fn from(value: &PrimitiveTag) -> Self {
324        match value {
325            PrimitiveTag::Boolean => 0x01,
326            PrimitiveTag::Integer => 0x02,
327            PrimitiveTag::BitString => 0x03,
328            PrimitiveTag::OctetString => 0x04,
329            PrimitiveTag::Null => 0x05,
330            PrimitiveTag::ObjectIdentifier => 0x06,
331            PrimitiveTag::UTF8String => 0x0c,
332            PrimitiveTag::Sequence => 0x10,
333            PrimitiveTag::Set => 0x11,
334            PrimitiveTag::PrintableString => 0x13,
335            PrimitiveTag::IA5String => 0x16,
336            PrimitiveTag::UTCTime => 0x17,
337            PrimitiveTag::GeneralizedTime => 0x18,
338            PrimitiveTag::BMPString => 0x1e,
339            PrimitiveTag::Unimplemented(value) => *value,
340        }
341    }
342}
343
344/// Tag-Length-Value structure representing a single DER element.
345///
346/// TLV is the basic building block of DER encoding. Each TLV consists of:
347/// - **Tag**: Identifies the data type
348/// - **Length**: Size of the value in bytes
349/// - **Value**: The actual data (either primitive bytes or nested TLVs)
350///
351/// Defined in [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690) Section 8.1.1.
352///
353/// # Example
354///
355/// ```
356/// use tsumiki_der::{Tlv, Tag, PrimitiveTag};
357///
358/// // Create a primitive TLV for INTEGER with value 42
359/// let tlv = Tlv::new_primitive(Tag::Primitive(PrimitiveTag::Integer, 0x02), vec![0x2a]);
360/// assert_eq!(tlv.data(), Some(&[0x2a][..]));
361/// ```
362#[derive(Debug, Clone, PartialEq, Eq)]
363pub struct Tlv {
364    tag: Tag,
365    // length: u64,
366    value: Value,
367}
368
369#[derive(Debug, Clone, PartialEq, Eq)]
370enum Value {
371    Tlv(Vec<Tlv>),
372    Data(Vec<u8>),
373}
374
375impl Tlv {
376    /// Returns the tag identifying the type of this TLV element.
377    pub fn tag(&self) -> &Tag {
378        &self.tag
379    }
380
381    /// Creates a new primitive TLV with raw byte data.
382    ///
383    /// Use this for primitive types like INTEGER, OCTET STRING, etc.
384    ///
385    /// # Example
386    ///
387    /// ```
388    /// use tsumiki_der::{Tlv, Tag, PrimitiveTag};
389    ///
390    /// let tlv = Tlv::new_primitive(Tag::Primitive(PrimitiveTag::Integer, 0x02), vec![0x2a]);
391    /// ```
392    pub fn new_primitive(tag: Tag, data: Vec<u8>) -> Self {
393        Tlv {
394            tag,
395            value: Value::Data(data),
396        }
397    }
398
399    /// Creates a new constructed TLV containing nested TLV elements.
400    ///
401    /// Use this for structured types like SEQUENCE or SET.
402    ///
403    /// # Example
404    ///
405    /// ```
406    /// use tsumiki_der::{Tlv, Tag, PrimitiveTag};
407    ///
408    /// let inner = Tlv::new_primitive(Tag::Primitive(PrimitiveTag::Integer, 0x02), vec![0x2a]);
409    /// let sequence = Tlv::new_constructed(Tag::Primitive(PrimitiveTag::Sequence, 0x30), vec![inner]);
410    /// ```
411    pub fn new_constructed(tag: Tag, tlvs: Vec<Tlv>) -> Self {
412        Tlv {
413            tag,
414            value: Value::Tlv(tlvs),
415        }
416    }
417
418    /// Returns the primitive data if this is a primitive TLV.
419    ///
420    /// Returns `None` if this is a constructed TLV containing nested elements.
421    pub fn data(&self) -> Option<&[u8]> {
422        match &self.value {
423            Value::Data(data) => Some(data),
424            Value::Tlv(_) => None,
425        }
426    }
427
428    /// Returns the nested TLV elements if this is a constructed TLV.
429    ///
430    /// Returns `None` if this is a primitive TLV containing raw data.
431    pub fn tlvs(&self) -> Option<&[Tlv]> {
432        match &self.value {
433            Value::Tlv(tlvs) => Some(tlvs),
434            Value::Data(_) => None,
435        }
436    }
437
438    /// Parses a TLV structure from DER-encoded bytes.
439    ///
440    /// This is an internal parsing function used by the decoder implementation.
441    pub(crate) fn parse(input: &[u8]) -> IResult<&[u8], Tlv> {
442        let (input, tag) = parse_tag(input)?;
443        let (input, length) = parse_length(input)?;
444        let (input, data) = nom::bytes::complete::take(length).parse(input)?;
445
446        if tag.is_constructed() {
447            // parse TLV recursively.
448            let mut tlvs = Vec::new();
449            let mut data = data;
450            while !data.is_empty() {
451                let (new_input, v) = Self::parse(data)?;
452                data = new_input;
453                tlvs.push(v);
454            }
455
456            return Ok((
457                input,
458                Tlv {
459                    tag,
460                    value: Value::Tlv(tlvs),
461                },
462            ));
463        }
464
465        Ok((
466            input,
467            Tlv {
468                tag,
469                value: Value::Data(data.to_vec()),
470            },
471        ))
472    }
473}
474
475impl EncodableTo<Tlv> for Vec<u8> {}
476
477impl Encoder<Tlv, Vec<u8>> for Tlv {
478    type Error = Error;
479
480    fn encode(&self) -> Result<Vec<u8>, Self::Error> {
481        // Get content bytes
482        let content = match &self.value {
483            Value::Data(data) => data.clone(),
484            Value::Tlv(tlvs) => tlvs
485                .iter()
486                .map(|tlv| tlv.encode())
487                .collect::<Result<Vec<_>, _>>()?
488                .into_iter()
489                .flatten()
490                .collect(),
491        };
492
493        // Build result: tag + length + content
494        let tag = self.tag.encode()?;
495        let length = encode_length(content.len());
496
497        Ok([tag].into_iter().chain(length).chain(content).collect())
498    }
499}
500
501/// Encodes a length value in DER format.
502///
503/// Uses short form (single byte) for lengths 0-127, and long form for larger lengths.
504/// Defined in [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690) Section 8.1.3.
505pub(crate) fn encode_length(length: usize) -> Vec<u8> {
506    if length < 0x80 {
507        // Short form: length fits in 7 bits (0-127)
508        vec![length as u8]
509    } else {
510        // Long form: first byte = 0x80 | number_of_length_bytes, followed by length bytes
511        let length_bytes: Vec<u8> = length
512            .to_be_bytes()
513            .into_iter()
514            .skip_while(|&b| b == 0) // Skip leading zero bytes
515            .collect();
516
517        [0x80 | length_bytes.len() as u8]
518            .into_iter()
519            .chain(length_bytes)
520            .collect()
521    }
522}
523
524/// Parses a tag byte from DER-encoded input.
525pub(crate) fn parse_tag(input: &[u8]) -> IResult<&[u8], Tag> {
526    let (input, n) = nom::number::be_u8().parse(input)?;
527    Ok((input, Tag::from(n)))
528}
529
530/// Parses a length field from DER-encoded input.
531///
532/// Supports both short form (0-127) and long form (128+) length encodings.
533/// Defined in [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690) Section 8.1.3.
534pub(crate) fn parse_length(input: &[u8]) -> IResult<&[u8], u64> {
535    let (input, n) = nom::number::be_u8().parse(input)?;
536    if n & 0x80 == 0x80 {
537        // long form
538        // First 1 bit is a marker for long form.
539        // Other bits represent bytes length of the length field.
540        let length = n & 0x7f;
541
542        // Sanity check: length field should not exceed 8 bytes for u64
543        if length > 8 {
544            return Err(nom::Err::Failure(nom::error::Error::new(
545                input,
546                nom::error::ErrorKind::TooLarge,
547            )));
548        }
549
550        let (input, bs) = nom::bytes::complete::take(length).parse(input)?;
551        let n = bs
552            .iter()
553            .enumerate()
554            .try_fold(0u64, |n, (i, &b)| {
555                let exp = (bs.len() - i - 1) as u32;
556                let base = 256_u64.checked_pow(exp)?;
557                let term = base.checked_mul(b as u64)?;
558                n.checked_add(term)
559            })
560            .ok_or_else(|| {
561                nom::Err::Failure(nom::error::Error::new(
562                    input,
563                    nom::error::ErrorKind::TooLarge,
564                ))
565            })?;
566        return Ok((input, n));
567    }
568    // short form: 0-127
569    Ok((input, n as u64))
570}
571
572#[cfg(test)]
573mod tests {
574    use rstest::rstest;
575
576    use crate::{Der, PrimitiveTag, Tag, Tlv, Value, parse_length};
577    use tsumiki::decoder::Decoder;
578    use tsumiki::encoder::Encoder;
579    use tsumiki_pem::Pem;
580
581    #[rstest(
582        input,
583        expected,
584        case(vec![0x02], Tag::Primitive(PrimitiveTag::Integer, 0x02)),
585        case(vec![0x02, 0x01], Tag::Primitive(PrimitiveTag::Integer, 0x02)),
586        case(vec![0x30, 0x01], Tag::Primitive(PrimitiveTag::Sequence, 0x30)),
587        case(vec![0x0a, 0x02, 0x10], Tag::Primitive(PrimitiveTag::Unimplemented(0x0a), 0x0a)),
588        // 0xA0 = 10100000 = context-specific [0] constructed
589        case(vec![0xa0], Tag::ContextSpecific { slot: 0x00, constructed: true }),
590        case(vec![0xa3], Tag::ContextSpecific { slot: 0x03, constructed: true }),
591        // 0x80 = 10000000 = context-specific [0] primitive
592        case(vec![0x80], Tag::ContextSpecific { slot: 0x00, constructed: false }),
593        case(vec![0x82], Tag::ContextSpecific { slot: 0x02, constructed: false }),
594    )]
595    fn test_parse_tag(input: Vec<u8>, expected: Tag) {
596        use crate::parse_tag;
597
598        let actual = parse_tag(&input).unwrap();
599
600        assert_eq!(expected, actual.1);
601    }
602
603    #[rstest(input, expected,
604        case(vec![0x02], 0x02),
605        case(vec![0x02, 0x01], 0x02),
606        case(vec![0x30, 0x01], 0x30),
607        case(vec![0x82, 0x02, 0x10], 256 * 0x02 + 0x10),
608        case(vec![0x83, 0x01, 0x00, 0x00], 256 * 256),
609        case(vec![0x82, 0xff, 0xff], 256 * 0xff + 0xff),
610    )]
611    fn test_parse_length(input: Vec<u8>, expected: u64) {
612        let actual = parse_length(&input).unwrap();
613
614        assert_eq!(expected, actual.1);
615    }
616
617    #[rstest(input, expected,
618        case(
619            vec![0x02, 0x01, 0x01],
620            Tlv{
621                tag: Tag::Primitive(PrimitiveTag::Integer, 0x02) ,
622                value: Value::Data(vec![0x01])
623            }
624        ),
625        case(
626            vec![0x02, 0x09, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
627            Tlv {
628                tag: Tag::Primitive(PrimitiveTag::Integer, 0x02),
629                value: Value::Data(vec![0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01])
630            }
631        ),
632        case(
633            vec![0x13, 0x02, 0x68, 0x69],
634            Tlv{
635                tag: Tag::Primitive(PrimitiveTag::PrintableString, 0x13),
636                value: Value::Data(vec![0x68, 0x69])
637            }
638        ),
639        case(
640            vec![0x16, 0x02, 0x68, 0x69],
641            Tlv{
642                tag: Tag::Primitive(PrimitiveTag::IA5String, 0x16),
643                value: Value::Data(vec![0x68, 0x69])
644            }
645        ),
646        case(
647            vec![0x0c, 0x04, 0xf0, 0x9f, 0x98, 0x8e],
648            Tlv{
649                tag: Tag::Primitive(PrimitiveTag::UTF8String, 0x0c),
650                value: Value::Data(vec![0xf0, 0x9f, 0x98, 0x8e])
651            }
652        ),
653        case(
654            vec![0x17, 0x11, 0x31, 0x39, 0x31, 0x32, 0x31, 0x35, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x2d, 0x30, 0x38, 0x30, 0x30],
655            Tlv {
656            tag: Tag::Primitive(PrimitiveTag::UTCTime, 0x17),
657            value: Value::Data(vec![
658                0x31, 0x39, 0x31, 0x32, 0x31, 0x35, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x2d, 0x30,
659                0x38, 0x30, 0x30,
660        ])}),
661        case(
662            vec![0x18, 0x0d, 0x31, 0x39, 0x31, 0x32, 0x31, 0x36, 0x30, 0x33, 0x30, 0x32, 0x31, 0x30, 0x5a],
663            Tlv{
664                tag: Tag::Primitive(PrimitiveTag::GeneralizedTime, 0x18),
665                value: Value::Data(vec![0x31, 0x39, 0x31, 0x32, 0x31, 0x36, 0x30, 0x33, 0x30, 0x32, 0x31, 0x30, 0x5a])
666            }
667        ),
668        case(
669            vec![0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b],
670            Tlv {
671                tag: Tag::Primitive(PrimitiveTag::ObjectIdentifier, 0x06),
672                 value: Value::Data(vec![0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b])
673            }
674        ),
675        case(
676            vec![0x05, 0x00],
677            Tlv {
678                tag: Tag::Primitive(PrimitiveTag::Null, 0x05),
679                value: Value::Data(vec![])
680            }
681        ),
682        case(
683            vec![0x04, 0x04, 0x03, 0x02, 0x06, 0xa0],
684            Tlv {
685                tag: Tag::Primitive(PrimitiveTag::OctetString, 0x04),
686                value: Value::Data(vec![0x03, 0x02, 0x06, 0xa0])
687            }
688        ),
689        case(
690            vec![0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0],
691            Tlv {
692                tag: Tag::Primitive(PrimitiveTag::BitString, 0x03),
693                value: Value::Data(vec![0x06, 0x6e, 0x5d, 0xc0])
694            }
695        )
696    )]
697    fn test_tlv_parse_primitive(input: Vec<u8>, expected: Tlv) {
698        let (_, actual) = Tlv::parse(&input).unwrap();
699        compare_primitive_tlv(&expected, &actual);
700    }
701
702    #[rstest(input, expected,
703        case(
704            vec![0x30, 0x09, 0x02, 0x01, 0x07, 0x02, 0x01, 0x08, 0x02, 0x01, 0x09],
705            Tlv {
706                tag: Tag::Primitive(PrimitiveTag::Sequence,  0x30),
707                value: Value::Tlv(
708                    vec![
709                        Tlv {
710                            tag: Tag::Primitive(PrimitiveTag::Integer, 0x02),
711                            value: Value::Data(vec![0x07])
712                        },
713                        Tlv {
714                            tag: Tag::Primitive(PrimitiveTag::Integer, 0x02),
715                            value: Value::Data(vec![0x08])
716                        },
717                        Tlv {
718                            tag: Tag::Primitive(PrimitiveTag::Integer, 0x02),
719                            value: Value::Data(vec![0x09])
720                        }
721                    ]
722                )
723            }
724        )
725    )]
726    fn test_tlv_parse_structured(input: Vec<u8>, expected: Tlv) {
727        let (_, actual) = Tlv::parse(&input).unwrap();
728        assert_eq!(expected.tag, actual.tag);
729        match actual.value {
730            Value::Data(_) => panic!("expected: Value::Tlv, but got Value::Data"),
731            Value::Tlv(actual_tlvs) => match expected.value {
732                Value::Data(_) => panic!("test data is invalid. required Value::Tlv"),
733                Value::Tlv(expected_tlvs) => {
734                    if actual_tlvs.len() != expected_tlvs.len() {
735                        panic!(
736                            "expected nested TLV length is {}, but got length is {}",
737                            expected_tlvs.len(),
738                            actual_tlvs.len()
739                        )
740                    }
741                    for (expected, actual) in expected_tlvs.iter().zip(actual_tlvs.iter()) {
742                        compare_primitive_tlv(expected, actual);
743                    }
744                }
745            },
746        }
747    }
748
749    fn compare_primitive_tlv(v1: &Tlv, v2: &Tlv) {
750        assert_eq!(v1.tag, v2.tag);
751        match &v2.value {
752            Value::Data(v2_data) => match &v1.value {
753                Value::Data(v1_data) => assert_eq!(v2_data, v1_data),
754                Value::Tlv(_) => panic!("test data is invalid. required Value::Data"),
755            },
756            Value::Tlv(tlvs) => {
757                panic!("v1: Value::Data, but got Value::Tlv({:?})", tlvs)
758            }
759        }
760    }
761
762    const TEST_PEM_CERT1: &str = r"-----BEGIN CERTIFICATE-----
763MIICLDCCAdKgAwIBAgIBADAKBggqhkjOPQQDAjB9MQswCQYDVQQGEwJCRTEPMA0G
764A1UEChMGR251VExTMSUwIwYDVQQLExxHbnVUTFMgY2VydGlmaWNhdGUgYXV0aG9y
765aXR5MQ8wDQYDVQQIEwZMZXV2ZW4xJTAjBgNVBAMTHEdudVRMUyBjZXJ0aWZpY2F0
766ZSBhdXRob3JpdHkwHhcNMTEwNTIzMjAzODIxWhcNMTIxMjIyMDc0MTUxWjB9MQsw
767CQYDVQQGEwJCRTEPMA0GA1UEChMGR251VExTMSUwIwYDVQQLExxHbnVUTFMgY2Vy
768dGlmaWNhdGUgYXV0aG9yaXR5MQ8wDQYDVQQIEwZMZXV2ZW4xJTAjBgNVBAMTHEdu
769dVRMUyBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkwWTATBgcqhkjOPQIBBggqhkjOPQMB
770BwNCAARS2I0jiuNn14Y2sSALCX3IybqiIJUvxUpj+oNfzngvj/Niyv2394BWnW4X
771uQ4RTEiywK87WRcWMGgJB5kX/t2no0MwQTAPBgNVHRMBAf8EBTADAQH/MA8GA1Ud
772DwEB/wQFAwMHBgAwHQYDVR0OBBYEFPC0gf6YEr+1KLlkQAPLzB9mTigDMAoGCCqG
773SM49BAMCA0gAMEUCIDGuwD1KPyG+hRf88MeyMQcqOFZD0TbVleF+UsAGQ4enAiEA
774l4wOuDwKQa+upc8GftXE2C//4mKANBC6It01gUaTIpo=
775-----END CERTIFICATE-----";
776
777    /*
778    * Generated by
779    $ openssl req -x509 -newkey rsa:2048 -nodes \
780        -keyout test_key.pem \
781        -out test_cert.pem \
782        -days 365 \
783        -subj "/C=JP/ST=Tokyo/L=Chiyoda/O=Test Org/OU=Test Unit/CN=localhost"
784    */
785    const TEST_PEM_CERT2: &str = r"-----BEGIN CERTIFICATE-----
786MIIDtTCCAp2gAwIBAgIUaFA0CT8XkKbEtG6JefcmPZp6ThowDQYJKoZIhvcNAQEL
787BQAwajELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMRAwDgYDVQQHDAdDaGl5
788b2RhMREwDwYDVQQKDAhUZXN0IE9yZzESMBAGA1UECwwJVGVzdCBVbml0MRIwEAYD
789VQQDDAlsb2NhbGhvc3QwHhcNMjUwNTIzMDkxMDQ3WhcNMjYwNTIzMDkxMDQ3WjBq
790MQswCQYDVQQGEwJKUDEOMAwGA1UECAwFVG9reW8xEDAOBgNVBAcMB0NoaXlvZGEx
791ETAPBgNVBAoMCFRlc3QgT3JnMRIwEAYDVQQLDAlUZXN0IFVuaXQxEjAQBgNVBAMM
792CWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALZBodqN
793qwafTo+pEyxjMfxHdGPsMLzdHAyHbnfIoaegpaSNG+Gj3XYg8om/F4IPwe73L9wf
7942QXjrA86fW4eSumwff+AlIc70wMUOHcJTRdRLNfF3O7BHgtS1Am9P3cANsw1IVec
7950DBYB8SZG0v7kt6EZ24ygznz1ptl0noKkVp6ocEUYC8B+Kr5qsm7qz2vef9QPlli
796IEm9Za0UFs/r1jjcxfz3GwYQkburRU+bdIO61SCiFyTsqp166XRNSN5ECINwjkxC
797CB/9QjeiKjNkyHfC6u1N8Is8fJVA6kUKFyTsPlvs9dzAi3AtNlQsN8p3uRKxZ7Ks
798E2hTchypMWozHCkCAwEAAaNTMFEwHQYDVR0OBBYEFPwPDgsW4wRdDj25yLSUYFzB
799YX8LMB8GA1UdIwQYMBaAFPwPDgsW4wRdDj25yLSUYFzBYX8LMA8GA1UdEwEB/wQF
800MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJOMSkpB5GWZRw4grEmDKmT8CODNvDBT
801S/btPF+unH0fssiqjdQ/qm/Q23Ry1y8paIvXT9IaCRDF5vYhM5A1S9+ryylIM+G4
802bAvsEgXUDmLB7LHzETg+7HSYe32iyh0p3EA/LAKdr3zh12bOAdQhRXooQdVjffhc
803AKftLxa4Xx7P+w/oPqOdt/f1BQyqsSdQ9iTCnvCbuZ2q3qzFf0ehZXiebXbU5zDc
804gqAQgXRgYgyMebhkGdi+V+G75ZSYgOD0zfcoL/p1fW9hr5PPqX7SXcyh8f8Q/ZIL
805fgx5sjr+fC3fvET/buw4EnKBhR+sSxn1T70hwP3aXd6wHN0vkMgaJPM=
806-----END CERTIFICATE-----";
807
808    const TEST_PEM_PRIV_KEY1: &str = r"-----BEGIN PRIVATE KEY-----
809MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2QaHajasGn06P
810qRMsYzH8R3Rj7DC83RwMh253yKGnoKWkjRvho912IPKJvxeCD8Hu9y/cH9kF46wP
811On1uHkrpsH3/gJSHO9MDFDh3CU0XUSzXxdzuwR4LUtQJvT93ADbMNSFXnNAwWAfE
812mRtL+5LehGduMoM589abZdJ6CpFaeqHBFGAvAfiq+arJu6s9r3n/UD5ZYiBJvWWt
813FBbP69Y43MX89xsGEJG7q0VPm3SDutUgohck7Kqdeul0TUjeRAiDcI5MQggf/UI3
814oiozZMh3wurtTfCLPHyVQOpFChck7D5b7PXcwItwLTZULDfKd7kSsWeyrBNoU3Ic
815qTFqMxwpAgMBAAECggEABSbYyOE9Rtwk79mjIZuSM6Pfbd2kyQnk+5OuczNYInFf
816jUWx1pB3t5mZ0Xv10abZYARbtXiu/UQgvnN0TTMNAgsLnLfJOwNdZRZivDaml7Sj
817NFwy8QrDayWFudrAGwCGDAKqdRwJJHywh4WeaGjtj12lwM8rt20lkVHw/6Mh1bFa
818Yo2mprDvq/xxqtmqL3I9iqbWPHRg4uGbq2lRD3UAE+Ig1nlY9TmdekNOvQxDLQGV
8190yGLVEE3Yjn9QYE+zs21iyYgV7NjEDw+FLzJ3yWb4UBtSiwAzd0XeOUgWx3IYEXF
820J/pSEFgBZdRm0JviQ2+qYH/4zKaWnhjwERa4D/H/UwKBgQD3wjoHG7bVCW7BMOWw
821mSFM7wZZ6nZItuaobPZbKXQxmXlbPEWJatW6bPcb9YAaw+VUWLXJyvD52N8M9r4E
822hUvUermCLrWU0rqD+0q1+j2iLqfzAg8X0jKYAJMR2ESBmDC8p/40xNOtFxG6uhST
823cUnykNbl0SYlDbWtYTSdkf5EowKBgQC8UZ/vCPx1PnF2ycdlGqZ/2valuR1EgHXK
824ce+mZmg62l4imkAxI3oJJHJh0r99x75yyzBMRhPJKq5P80x6KpqZfH8DBMfWF4fu
82583ark/KQXe4M6RAkH+/MH2jsFWpg9c6WQleizoky8bLaDfBGZyVfHfY+FL0Z/zHj
826IXhtDyEcwwKBgQDkjs7NQ+nUedEsc5lQ4tLvkAmB5WOdDO2YLnzN+F3ya6yiV+Wm
827MWJdiqwjpMS67EChIP0C3S6UrlaGNRFyRi2AJH8B82kbk5Lwsl9npSQ6e2QAL8QQ
828q550zwLdkW8RRn6fazJ9J55GrWNzqLnWksou9SLp+5l+0TjqayQIwGealQKBgGby
829rF7tZ63kg/yvVBzWU90jY6C3MOPI4hvY62zpIOPDiqCZ+KukPEuRLCKEJoDpWBjD
830MVURHjHj7kTwuYczkS6FG54X1/MXDA259M7ZY0o+vys5ocRN3TaWmTIuhugYmGYW
831QHhVNjWuYdrIseia7Jgx9fJ8PeBfXPNQ0de05KInAoGAbbsbgtWqL5E9aWn2d0BN
832MYfyU9h1doVwVB/ZdzPtS6BuzrtfZ+Oov86tHqnEvUPs7C8Nvzx8HXbT5mdnSgea
833RJi/eAqNhqr/YHf8CvlRjMWHnNLlzqrST9aHKeZwPNr+1o/2PeEZCPShUAHZKmf9
834e8ZYGIc4gvs5McdrVUyYGUs=
835-----END PRIVATE KEY-----";
836
837    #[rstest(
838        input,
839        _expected,
840        case(TEST_PEM_CERT1, None),
841        case(TEST_PEM_CERT2, None),
842        case(TEST_PEM_PRIV_KEY1, None)
843    )]
844    fn test_decode_der_from_pem(input: &str, _expected: Option<()>) {
845        let pem = input.decode().unwrap();
846        // Assuming not to panic here.
847        let der: Der = pem.decode().unwrap();
848        println!("{:?}", der);
849    }
850
851    #[rstest(cert_pem, case(TEST_PEM_CERT1), case(TEST_PEM_CERT2))]
852    fn test_roundtrip_der_encode(cert_pem: &str) {
853        // PEM -> Der -> Vec<u8> -> Der
854        let pem: Pem = cert_pem.parse().expect("Failed to parse PEM");
855        let original_der: Der = pem.decode().expect("Failed to decode PEM to Der");
856
857        let encoded_bytes = original_der
858            .encode()
859            .expect("Failed to encode Der to Vec<u8>");
860        let decoded_der: Der = encoded_bytes
861            .decode()
862            .expect("Failed to decode Vec<u8> to Der");
863
864        assert_eq!(original_der, decoded_der);
865    }
866}