Skip to content

Commit

Permalink
feat(asn1-parser): implement Enumerated type;
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBestTvarynka committed Aug 23, 2024
1 parent 4e209fd commit b5bbec4
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 5 deletions.
3 changes: 2 additions & 1 deletion crates/asn1-parser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ This `asn1` parser is aimed to parse input bytes and return an AST as the result
---

- [X] [Integer](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/integer.html)
- [X] [Enumerated](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/enumerated.html)
- [X] [Boolean](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/boolean.html)
- [X] [Null](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/null.html)
- [X] [ObjectIdentifier](https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier)
Expand All @@ -61,4 +62,4 @@ This `asn1` parser is aimed to parse input bytes and return an AST as the result

```rust
todo!();
```
```
19 changes: 15 additions & 4 deletions crates/asn1-parser/src/asn1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use core::ops::Range;
use crate::reader::Reader;
use crate::writer::Writer;
use crate::{
ApplicationTag, Asn1Encoder, Asn1Result, Asn1ValueDecoder, BitString, BmpString, Bool, Error, ExplicitTag,
GeneralString, GeneralizedTime, IA5String, ImplicitTag, Integer, MetaInfo, Null, NumericString, ObjectIdentifier,
OctetString, PrintableString, Sequence, Set, Tag, Taggable, Tlv, UtcTime, Utf8String, VisibleString,
ApplicationTag, Asn1Encoder, Asn1Result, Asn1ValueDecoder, BitString, BmpString, Bool, Enumerated, Error,
ExplicitTag, GeneralString, GeneralizedTime, IA5String, ImplicitTag, Integer, MetaInfo, Null, NumericString,
ObjectIdentifier, OctetString, PrintableString, Sequence, Set, Tag, Taggable, Tlv, UtcTime, Utf8String,
VisibleString,
};

#[derive(Debug, Clone, PartialEq, Eq)]
Expand All @@ -30,6 +31,7 @@ pub enum Asn1Type<'data> {
Bool(Bool),
Null(Null),
Integer(Integer<'data>),
Enumerated(Enumerated<'data>),
ObjectIdentifier(ObjectIdentifier),

ExplicitTag(ExplicitTag<'data>),
Expand Down Expand Up @@ -58,6 +60,7 @@ impl Asn1Type<'_> {
Asn1Type::Bool(b) => Asn1Type::Bool(b.clone()),
Asn1Type::Null(n) => Asn1Type::Null(n.clone()),
Asn1Type::Integer(i) => Asn1Type::Integer(i.to_owned()),
Asn1Type::Enumerated(e) => Asn1Type::Enumerated(e.to_owned()),
Asn1Type::ObjectIdentifier(o) => Asn1Type::ObjectIdentifier(o.clone()),
Asn1Type::ExplicitTag(e) => Asn1Type::ExplicitTag(e.to_owned()),
Asn1Type::ImplicitTag(i) => Asn1Type::ImplicitTag(i.to_owned()),
Expand Down Expand Up @@ -86,6 +89,7 @@ impl Taggable for Asn1Type<'_> {
Asn1Type::Bool(b) => b.tag(),
Asn1Type::Null(n) => n.tag(),
Asn1Type::Integer(i) => i.tag(),
Asn1Type::Enumerated(e) => e.tag(),
Asn1Type::ObjectIdentifier(o) => o.tag(),
Asn1Type::ExplicitTag(e) => e.tag(),
Asn1Type::ImplicitTag(i) => i.tag(),
Expand All @@ -97,7 +101,10 @@ impl Taggable for Asn1Type<'_> {
}

impl<'data> Asn1ValueDecoder<'data> for Asn1Type<'data> {
#[instrument(level = "debug", ret)]
fn decode(tag: Tag, reader: &mut Reader<'data>) -> Asn1Result<Self> {
debug!(?tag);

decode_asn1!(
OctetString,
Utf8String,
Expand All @@ -112,6 +119,7 @@ impl<'data> Asn1ValueDecoder<'data> for Asn1Type<'data> {
VisibleString,
Bool,
Integer,
Enumerated,
ObjectIdentifier,
ExplicitTag,
ImplicitTag,
Expand All @@ -122,7 +130,7 @@ impl<'data> Asn1ValueDecoder<'data> for Asn1Type<'data> {
in tag, reader
);

Err(Error::from("Invalid asn1 data"))
Err(Error::from("Invalid or unsupported asn1 tag"))
}

fn compare_tags(_tag: Tag) -> bool {
Expand All @@ -146,6 +154,7 @@ impl Asn1Encoder for Asn1Type<'_> {
Asn1Type::VisibleString(g) => g.needed_buf_size(),
Asn1Type::Bool(boolean) => boolean.needed_buf_size(),
Asn1Type::Integer(integer) => integer.needed_buf_size(),
Asn1Type::Enumerated(enumerated) => enumerated.needed_buf_size(),
Asn1Type::ObjectIdentifier(object_identifier) => object_identifier.needed_buf_size(),
Asn1Type::ExplicitTag(e) => e.needed_buf_size(),
Asn1Type::ImplicitTag(i) => i.needed_buf_size(),
Expand All @@ -171,6 +180,7 @@ impl Asn1Encoder for Asn1Type<'_> {
Asn1Type::VisibleString(numeric) => numeric.encode(writer),
Asn1Type::Bool(boolean) => boolean.encode(writer),
Asn1Type::Integer(integer) => integer.encode(writer),
Asn1Type::Enumerated(enumerated) => enumerated.encode(writer),
Asn1Type::ObjectIdentifier(object_identifier) => object_identifier.encode(writer),
Asn1Type::ExplicitTag(e) => e.encode(writer),
Asn1Type::ImplicitTag(i) => i.encode(writer),
Expand Down Expand Up @@ -198,6 +208,7 @@ impl MetaInfo for Asn1Type<'_> {
Asn1Type::VisibleString(_) => {}
Asn1Type::Bool(_) => {}
Asn1Type::Integer(_) => {}
Asn1Type::Enumerated(_) => {}
Asn1Type::ObjectIdentifier(_) => {}
Asn1Type::ExplicitTag(explicit_tag) => explicit_tag.clear_meta(),
Asn1Type::ImplicitTag(implicit_tag) => implicit_tag.clear_meta(),
Expand Down
76 changes: 76 additions & 0 deletions crates/asn1-parser/src/primitives/enumerated.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use alloc::borrow::Cow;
use alloc::vec::Vec;

use num_bigint_dig::BigUint;

use crate::length::{len_size, write_len};
use crate::reader::Reader;
use crate::writer::Writer;
use crate::{Asn1Encoder, Asn1Result, Asn1ValueDecoder, Tag, Taggable};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Enumerated<'data>(Cow<'data, [u8]>);

pub type OwnedEnumerated = Enumerated<'static>;

impl Enumerated<'_> {
pub const TAG: Tag = Tag(10);

pub fn raw_data(&self) -> &[u8] {
self.0.as_ref()
}

pub fn as_big_uint(&self) -> BigUint {
BigUint::from_bytes_be(if self.0.len() > 1 {
if self.0[0] == 0x00 {
&self.0[1..]
} else {
&self.0
}
} else if self.0.is_empty() {
&[0]
} else {
&self.0
})
}

pub fn to_owned(&self) -> OwnedEnumerated {
Enumerated(Cow::Owned(self.0.as_ref().to_vec()))
}
}

impl From<Vec<u8>> for OwnedEnumerated {
fn from(bytes: Vec<u8>) -> Self {
Self(Cow::Owned(bytes))
}
}

impl Taggable for Enumerated<'_> {
fn tag(&self) -> Tag {
Self::TAG
}
}

impl<'data> Asn1ValueDecoder<'data> for Enumerated<'data> {
fn decode(_: Tag, reader: &mut Reader<'data>) -> Asn1Result<Self> {
Ok(Self(Cow::Borrowed(reader.remaining())))
}

fn compare_tags(tag: Tag) -> bool {
Self::TAG == tag
}
}

impl Asn1Encoder for Enumerated<'_> {
fn needed_buf_size(&self) -> usize {
let data_len = self.0.len();

1 /* tag */ + len_size(data_len) + data_len
}

fn encode(&self, writer: &mut Writer) -> Asn1Result<()> {
writer.write_byte(Self::TAG.into())?;
write_len(self.0.len(), writer)?;
writer.write_slice(self.0.as_ref())
}
}
2 changes: 2 additions & 0 deletions crates/asn1-parser/src/primitives/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod boolean;
mod enumerated;
mod integer;
mod null;
mod object_identifier;

pub use boolean::Bool;
pub use enumerated::{Enumerated, OwnedEnumerated};
pub use integer::{Integer, OwnedInteger};
pub use null::Null;
pub use object_identifier::ObjectIdentifier;
2 changes: 2 additions & 0 deletions crates/asn1-parser/src/tlv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ impl<'data, A: Asn1ValueDecoder<'data> + Debug> Asn1Decoder<'data> for Tlv<'data

let (data, data_range) = read_data(reader, len)?;

trace!(?tag, ?len, ?data);

let mut inner_reader = Reader::new(data);
inner_reader.set_next_id(reader.next_id());
inner_reader.set_offset(reader.full_offset() - data.len());
Expand Down

0 comments on commit b5bbec4

Please sign in to comment.