Skip to content

Commit

Permalink
Merge pull request #50 from TheBestTvarynka/asn1-types
Browse files Browse the repository at this point in the history
More asn1 types
  • Loading branch information
TheBestTvarynka authored Jan 25, 2024
2 parents 5547002 + fa53202 commit 9da83b1
Show file tree
Hide file tree
Showing 49 changed files with 1,818 additions and 219 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,6 @@ bcrypt = "0.14.0"
flate2 = { version = "1.0.26", features = ["zlib"] }

# asn1
asn1-parser = { path = "./crates/asn1-parser" }
asn1-parser = { path = "./crates/asn1-parser", features = ["std"] }
oid = { version = "0.2.1", default-features = false }
paste = "1.0.14"
3 changes: 3 additions & 0 deletions crates/asn1-parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ proptest = "1.2.0"
[dependencies]
log = "0.4.20"
num-bigint-dig = { version = "0.8.4", default-features = false }
num-traits = { version = "0.2.17", default-features = false }
oid = { version = "0.2.1", default-features = false }
paste = "1.0.14"
27 changes: 12 additions & 15 deletions crates/asn1-parser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ This `asn1` parser is aimed to parse input bytes and return an AST as the result
- [X] [BitString](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/bitstring.html)
- [X] [BmpString](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/bmpstring.html)
- [ ] [GraphicString](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/graphicstring.html)
- [ ] [IA5String](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/ia5string.html)
- [ ] [GeneralString](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/generalstring.html)
- [ ] [PrintableString](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/printablestring.html)
- [X] [IA5String](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/ia5string.html)
- [X] [GeneralString](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/generalstring.html)
- [X] [PrintableString](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/printablestring.html)
- [X] [OctetString](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/octetstring.html)
- [ ] [NumericString](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/numericstring.html)
- [ ] [UniversalString](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/universalstring.html)
Expand All @@ -30,38 +30,35 @@ This `asn1` parser is aimed to parse input bytes and return an AST as the result

---

- [ ] [Date](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/utf8string.html)
- [ ] [DateTime](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/datetime.html)
- [ ] [Duration](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/duration.html)
- [ ] [GeneralizedTime](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/generalizedtime.html)
- [X] [GeneralizedTime](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/generalizedtime.html)
- [ ] [Time](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/time.html)
- [ ] [UtcTime](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/utctime.html)
- [X] [UtcTime](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/utctime.html)
- [ ] [TimeOfDay](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/timeofday.html)

---

- [X] [Integer](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/integer.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)
- [ ] [ObjectIdentifier](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/object-identifier.html)
- [X] [ObjectIdentifier](https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier)
- [ ] [Real](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/real.html)

---

- [X] [Sequence](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/sequence.html)
- [ ] [SequenceOf](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/sequenceof.html)
- [ ] [Set](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/set.html)
- [ ] [SetOf](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/setof.html)
- [ ] [Choice](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/choice.html)
- [X] ~~[SequenceOf](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/sequenceof.html).~~ _Note. This library doesn't have a separate type for the_ `SequenceOf` _ASN1 data type. Just use the regular_ `Suquence` _for it. Their tags are the same, so no problem should occur._
- [X] [Set](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/set.html)
- [X] ~~[SetOf](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/setof.html).~~ _Note. This library doesn't have a separate type for the_ `SetOf` _ASN1 data type. Just use the regular_ `Set` _for it. Their tags are the same, so no problem should occur._
- [X] ~~[Choice](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/choice.html).~~ _Note. We don't need a separate type for the ASN1_ `Choice` _type because it will still be parsed into some ASN1 object._

---

- [X] [ExplicitTag](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/asn1-tags.html)
- [ ] [ImplicitTag](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/asn1-tags.html)
- [X] [ImplicitTag](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/asn1-tags.html)
- [X] [ApplicationTag](https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/asn1-tags.html)

## Usage example

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

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Asn1Type<'data> {
Sequence(Sequence<'data>),
Set(Set<'data>),

OctetString(OctetString<'data>),
Utf8String(Utf8String<'data>),
BitString(BitString<'data>),
BmpString(BmpString<'data>),
IA5String(IA5String<'data>),
PrintableString(PrintableString<'data>),
GeneralString(GeneralString<'data>),

UtcTime(UtcTime),
GeneralizedTime(GeneralizedTime),

Bool(Bool),
Null(Null),
Integer(Integer<'data>),
ObjectIdentifier(ObjectIdentifier),

ExplicitTag(ExplicitTag<'data>),
ImplicitTag(ImplicitTag<'data>),
ApplicationTag(ApplicationTag<'data>),
}

Expand All @@ -33,15 +44,23 @@ impl Asn1Type<'_> {
pub fn to_owned(&self) -> OwnedAsn1Type {
match self {
Asn1Type::Sequence(s) => Asn1Type::Sequence(s.to_owned()),
Asn1Type::Set(s) => Asn1Type::Set(s.to_owned()),
Asn1Type::OctetString(o) => Asn1Type::OctetString(o.to_owned()),
Asn1Type::Utf8String(u) => Asn1Type::Utf8String(u.to_owned()),
Asn1Type::BitString(b) => Asn1Type::BitString(b.to_owned()),
Asn1Type::IA5String(i) => Asn1Type::IA5String(i.to_owned()),
Asn1Type::PrintableString(p) => Asn1Type::PrintableString(p.to_owned()),
Asn1Type::GeneralString(g) => Asn1Type::GeneralString(g.to_owned()),
Asn1Type::Bool(b) => Asn1Type::Bool(b.clone()),
Asn1Type::Null(n) => Asn1Type::Null(n.clone()),
Asn1Type::Integer(i) => Asn1Type::Integer(i.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()),
Asn1Type::ApplicationTag(a) => Asn1Type::ApplicationTag(a.to_owned()),
Asn1Type::BmpString(b) => Asn1Type::BmpString(b.to_owned()),
Asn1Type::UtcTime(u) => Asn1Type::UtcTime(u.clone()),
Asn1Type::GeneralizedTime(u) => Asn1Type::GeneralizedTime(u.clone()),
}
}
}
Expand All @@ -50,44 +69,52 @@ impl Taggable for Asn1Type<'_> {
fn tag(&self) -> Tag {
match self {
Asn1Type::Sequence(s) => s.tag(),
Asn1Type::Set(s) => s.tag(),
Asn1Type::OctetString(o) => o.tag(),
Asn1Type::Utf8String(u) => u.tag(),
Asn1Type::BitString(b) => b.tag(),
Asn1Type::BmpString(b) => b.tag(),
Asn1Type::IA5String(i) => i.tag(),
Asn1Type::PrintableString(p) => p.tag(),
Asn1Type::GeneralString(g) => g.tag(),
Asn1Type::Bool(b) => b.tag(),
Asn1Type::Null(n) => n.tag(),
Asn1Type::Integer(i) => i.tag(),
Asn1Type::ObjectIdentifier(o) => o.tag(),
Asn1Type::ExplicitTag(e) => e.tag(),
Asn1Type::ImplicitTag(i) => i.tag(),
Asn1Type::ApplicationTag(a) => a.tag(),
Asn1Type::UtcTime(u) => u.tag(),
Asn1Type::GeneralizedTime(u) => u.tag(),
}
}
}

impl<'data> Asn1ValueDecoder<'data> for Asn1Type<'data> {
fn decode(tag: Tag, reader: &mut Reader<'data>) -> Asn1Result<Self> {
if OctetString::compare_tags(tag) {
Ok(Asn1Type::OctetString(OctetString::decode(tag, reader)?))
} else if Utf8String::compare_tags(tag) {
Ok(Asn1Type::Utf8String(Utf8String::decode(tag, reader)?))
} else if Sequence::compare_tags(tag) {
Ok(Asn1Type::Sequence(Sequence::decode(tag, reader)?))
} else if BitString::compare_tags(tag) {
Ok(Asn1Type::BitString(BitString::decode(tag, reader)?))
} else if BmpString::compare_tags(tag) {
Ok(Asn1Type::BmpString(BmpString::decode(tag, reader)?))
} else if Bool::compare_tags(tag) {
Ok(Asn1Type::Bool(Bool::decode(tag, reader)?))
} else if Integer::compare_tags(tag) {
Ok(Asn1Type::Integer(Integer::decode(tag, reader)?))
} else if ExplicitTag::compare_tags(tag) {
Ok(Asn1Type::ExplicitTag(ExplicitTag::decode(tag, reader)?))
} else if ApplicationTag::compare_tags(tag) {
Ok(Asn1Type::ApplicationTag(ApplicationTag::decode(tag, reader)?))
} else if Null::compare_tags(tag) {
Ok(Asn1Type::Null(Null::decode(tag, reader)?))
} else {
Err(Error::from("Invalid data"))
}
decode_asn1!(
OctetString,
Utf8String,
Sequence,
Set,
BitString,
BmpString,
IA5String,
PrintableString,
GeneralString,
Bool,
Integer,
ObjectIdentifier,
ExplicitTag,
ImplicitTag,
ApplicationTag,
Null,
UtcTime,
GeneralizedTime;
in tag, reader
);

Err(Error::from("Invalid asn1 data"))
}

fn compare_tags(_tag: Tag) -> bool {
Expand All @@ -101,13 +128,21 @@ impl Asn1Encoder for Asn1Type<'_> {
Asn1Type::OctetString(octet) => octet.needed_buf_size(),
Asn1Type::Utf8String(utf8) => utf8.needed_buf_size(),
Asn1Type::Sequence(sequence) => sequence.needed_buf_size(),
Asn1Type::Set(set) => set.needed_buf_size(),
Asn1Type::BitString(bit) => bit.needed_buf_size(),
Asn1Type::BmpString(bmp) => bmp.needed_buf_size(),
Asn1Type::IA5String(i) => i.needed_buf_size(),
Asn1Type::PrintableString(p) => p.needed_buf_size(),
Asn1Type::GeneralString(g) => g.needed_buf_size(),
Asn1Type::Bool(boolean) => boolean.needed_buf_size(),
Asn1Type::Integer(integer) => integer.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(),
Asn1Type::ApplicationTag(a) => a.needed_buf_size(),
Asn1Type::Null(n) => n.needed_buf_size(),
Asn1Type::UtcTime(u) => u.needed_buf_size(),
Asn1Type::GeneralizedTime(u) => u.needed_buf_size(),
}
}

Expand All @@ -116,30 +151,46 @@ impl Asn1Encoder for Asn1Type<'_> {
Asn1Type::OctetString(octet) => octet.encode(writer),
Asn1Type::Utf8String(utf8) => utf8.encode(writer),
Asn1Type::Sequence(sequence) => sequence.encode(writer),
Asn1Type::Set(set) => set.encode(writer),
Asn1Type::BitString(bit) => bit.encode(writer),
Asn1Type::BmpString(bmp) => bmp.encode(writer),
Asn1Type::IA5String(ia5) => ia5.encode(writer),
Asn1Type::PrintableString(printable) => printable.encode(writer),
Asn1Type::GeneralString(general) => general.encode(writer),
Asn1Type::Bool(boolean) => boolean.encode(writer),
Asn1Type::Integer(integer) => integer.encode(writer),
Asn1Type::ObjectIdentifier(object_identifier) => object_identifier.encode(writer),
Asn1Type::ExplicitTag(e) => e.encode(writer),
Asn1Type::ImplicitTag(i) => i.encode(writer),
Asn1Type::ApplicationTag(a) => a.encode(writer),
Asn1Type::Null(n) => n.encode(writer),
Asn1Type::UtcTime(utc_time) => utc_time.encode(writer),
Asn1Type::GeneralizedTime(generalized_time) => generalized_time.encode(writer),
}
}
}

impl MetaInfo for Asn1Type<'_> {
fn clear_meta(&mut self) {
match self {
Asn1Type::OctetString(_) => {}
Asn1Type::OctetString(octet_string) => octet_string.clear_meta(),
Asn1Type::Utf8String(_) => {}
Asn1Type::Sequence(sequence) => sequence.clear_meta(),
Asn1Type::Set(set) => set.clear_meta(),
Asn1Type::BitString(_) => {}
Asn1Type::BmpString(_) => {}
Asn1Type::IA5String(_) => {}
Asn1Type::PrintableString(_) => {}
Asn1Type::GeneralString(_) => {}
Asn1Type::Bool(_) => {}
Asn1Type::Integer(_) => {}
Asn1Type::ObjectIdentifier(_) => {}
Asn1Type::ExplicitTag(explicit_tag) => explicit_tag.clear_meta(),
Asn1Type::ImplicitTag(implicit_tag) => implicit_tag.clear_meta(),
Asn1Type::ApplicationTag(application_tag) => application_tag.clear_meta(),
Asn1Type::Null(_) => {}
Asn1Type::UtcTime(_) => {}
Asn1Type::GeneralizedTime(_) => {}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/asn1-parser/src/constructors/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod sequence;
mod set;

pub use sequence::{OwnedSequence, Sequence};
pub use set::{OwnedSet, Set};
2 changes: 2 additions & 0 deletions crates/asn1-parser/src/constructors/sequence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ pub struct Sequence<'data>(Vec<Asn1<'data>>);
pub type OwnedSequence = Sequence<'static>;

impl Sequence<'_> {
/// Tag value of the [SEQUENCE] type
pub const TAG: Tag = Tag(0x30);

/// Creates a new [Sequence] from passed fields
pub fn new(fields: Vec<Asn1>) -> Sequence {
Sequence(fields)
}
Expand Down
Loading

0 comments on commit 9da83b1

Please sign in to comment.