Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,153 @@
|
||||
// Copyright (c) 2022, 2024 blackshirt. All rights reserved.
|
||||
// Use of this source code is governed by a MIT License
|
||||
// that can be found in the LICENSE file.
|
||||
module asn1
|
||||
|
||||
// common parsing routines
|
||||
//
|
||||
fn parse_element(tag Tag, content []u8) !Element {
|
||||
match tag.class {
|
||||
.universal {
|
||||
return parse_universal(tag, content)!
|
||||
}
|
||||
.context_specific {
|
||||
return parse_context_specific(tag, content)!
|
||||
}
|
||||
.application {
|
||||
return parse_application(tag, content)!
|
||||
}
|
||||
.private {
|
||||
return parse_private(tag, content)!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_universal(tag Tag, content []u8) !Element {
|
||||
if tag.class != .universal {
|
||||
return error('Non universal class')
|
||||
}
|
||||
if tag.constructed {
|
||||
return parse_universal_constructed(tag, content)!
|
||||
}
|
||||
return parse_universal_primitive(tag, content)!
|
||||
}
|
||||
|
||||
fn parse_universal_primitive(tag Tag, content []u8) !Element {
|
||||
if tag.constructed {
|
||||
return error('parse on constructed type')
|
||||
}
|
||||
match tag.tag_number() {
|
||||
int(TagType.boolean) {
|
||||
return Boolean.from_bytes(content)!
|
||||
}
|
||||
int(TagType.null) {
|
||||
return Null.from_bytes(content)!
|
||||
}
|
||||
int(TagType.oid) {
|
||||
return ObjectIdentifier.from_bytes(content)!
|
||||
}
|
||||
int(TagType.integer) {
|
||||
return Integer.from_bytes(content)!
|
||||
}
|
||||
int(TagType.enumerated) {
|
||||
return Enumerated.from_bytes(content)!
|
||||
}
|
||||
int(TagType.bitstring) {
|
||||
return BitString.from_bytes(content)!
|
||||
}
|
||||
int(TagType.ia5string) {
|
||||
return IA5String.from_bytes(content)!
|
||||
}
|
||||
int(TagType.utf8string) {
|
||||
return Utf8String.from_bytes(content)!
|
||||
}
|
||||
int(TagType.numericstring) {
|
||||
return NumericString.from_bytes(content)!
|
||||
}
|
||||
int(TagType.printablestring) {
|
||||
return PrintableString.from_bytes(content)!
|
||||
}
|
||||
int(TagType.generalstring) {
|
||||
return GeneralString.from_bytes(content)!
|
||||
}
|
||||
int(TagType.octetstring) {
|
||||
return OctetString.from_bytes(content)!
|
||||
}
|
||||
int(TagType.visiblestring) {
|
||||
return VisibleString.from_bytes(content)!
|
||||
}
|
||||
int(TagType.utctime) {
|
||||
return UtcTime.from_bytes(content)!
|
||||
}
|
||||
int(TagType.generalizedtime) {
|
||||
return GeneralizedTime.from_bytes(content)!
|
||||
}
|
||||
else {
|
||||
// return the raw element
|
||||
return RawElement.new(tag, content)!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_universal_constructed(tag Tag, content []u8) !Element {
|
||||
if !tag.constructed {
|
||||
return error('parse on non-constructed type')
|
||||
}
|
||||
match tag.tag_number() {
|
||||
int(TagType.sequence) {
|
||||
// todo: handle SequenceOf
|
||||
return Sequence.from_bytes(content)!
|
||||
}
|
||||
int(TagType.set) {
|
||||
return Set.from_bytes(content)!
|
||||
}
|
||||
else {
|
||||
return RawElement.new(tag, content)!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_private(tag Tag, content []u8) !PrivateELement {
|
||||
return PrivateELement.new(tag, content)!
|
||||
}
|
||||
|
||||
fn parse_application(tag Tag, content []u8) !ApplicationElement {
|
||||
return ApplicationElement.new(tag, content)!
|
||||
}
|
||||
|
||||
// parse_context_specific_with_mode parses tag and content as ContextElement when mode is availables
|
||||
fn parse_context_specific_with_mode(tag Tag, content []u8, inner_tag Tag, mode TaggedMode) !ContextElement {
|
||||
if tag.tag_class() != .context_specific {
|
||||
return error('parse on non-context-specific class')
|
||||
}
|
||||
if mode == .implicit {
|
||||
inner := parse_element(inner_tag, content)!
|
||||
ctx := ContextElement.from_element(inner, tag.number, mode)!
|
||||
return ctx
|
||||
}
|
||||
// explicit
|
||||
// read an inner tag from content
|
||||
mut p := Parser.new(content)
|
||||
intag := p.peek_tag()!
|
||||
if !intag.equal(inner_tag) {
|
||||
return error('Get unexpected inner tag')
|
||||
}
|
||||
inner_el := p.read_tlv()!
|
||||
// should finish
|
||||
p.finish()!
|
||||
|
||||
ctx := ContextElement.from_element(inner_el, tag.number, .explicit)!
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
// parse_context_specific parses tag and content as ContextElement.
|
||||
// The info of fields of ContextElement, ie, inner_tag and mode, is not availables here
|
||||
// You should provides this later with the correct value.
|
||||
fn parse_context_specific(tag Tag, content []u8) !ContextElement {
|
||||
// mode and inner_tag is not set here without additional information,
|
||||
// So its still none here, and you should set it with correct value
|
||||
ctx := ContextElement.new(tag, content)!
|
||||
|
||||
return ctx
|
||||
}
|
||||
Reference in new issue
Block a user