/// <summary> /// Initializes a new instance of the <see cref="Asn1TagInfo"/> struct. /// </summary> /// <param name="asn1Tag">The asn1 tag.</param> /// <param name="constructType">Type of the construct.</param> public Asn1TagInfo(Asn1Tag asn1Tag, ConstructType constructType) { this.Asn1ClassType = Asn1Class.Universal; this.Asn1ConstructType = constructType; this.Asn1SnmpTagType = Asn1SnmpTag.NotSnmpData; this.Asn1TagType = asn1Tag; }
/// <summary> /// Initializes a new instance of the <see cref="Asn1TagInfo"/> struct. /// </summary> /// <param name="asn1Tag">The asn1 tag.</param> /// <param name="constructType">Type of the construct.</param> /// <param name="asn1Class">The asn1 class.</param> public Asn1TagInfo(Asn1Tag asn1Tag, ConstructType constructType, Asn1Class asn1Class) { this.Asn1ClassType = asn1Class; this.Asn1ConstructType = constructType; this.Asn1SnmpTagType = Asn1SnmpTag.NotSnmpData; this.Asn1TagType = asn1Tag; }
/// <summary> /// Initializes a new instance of the <see cref="Asn1TagInfo"/> struct. /// </summary> /// <param name="asn1SnmpTag">The asn1 SNMP tag.</param> /// <param name="constructType">Type of the construct.</param> public Asn1TagInfo(Asn1SnmpTag asn1SnmpTag, ConstructType constructType) { this.Asn1ClassType = Asn1Class.Application; this.Asn1ConstructType = constructType; this.Asn1SnmpTagType = asn1SnmpTag; this.Asn1TagType = Asn1Tag.NotAsn1Data; }
/// <summary> /// Initializes a new instance of the <see cref="Asn1TagInfo"/> struct. /// </summary> /// <param name="asn1SnmpTag">The asn1 SNMP tag.</param> /// <param name="constructType">Type of the construct.</param> public Asn1TagInfo(Asn1SnmpTag asn1SnmpTag, ConstructType constructType) { Asn1ClassType = Asn1Class.Application; Asn1ConstructType = constructType; Asn1SnmpTagType = asn1SnmpTag; Asn1TagType = Asn1Tag.NotAsn1Data; }
/// <summary> /// Initializes a new instance of the <see cref="Asn1Object{T}"/> class. /// </summary> /// <param name="asn1Class">Class of given Asn.1 object.</param> /// <param name="constructed">Constructed/Primitive bit of identifier octet.</param> /// <param name="asn1Tag">Tag number or type of Asn.1 object.</param> /// <param name="content">Raw content to be decoded.</param> protected Asn1Object(Asn1Class asn1Class, bool constructed, int asn1Tag, SubStream content) : base(asn1Class, constructed, asn1Tag) { this.RawContent = content; this.RawContent.Seek(this.RawContent.Length, SeekOrigin.Current); this.toBeParsed = true; }
/// <summary> /// Initializes a new instance of the <see cref="Asn1TagInfo"/> struct. /// </summary> /// <param name="asn1Tag">The asn1 tag.</param> /// <param name="constructType">Type of the construct.</param> public Asn1TagInfo(Asn1Tag asn1Tag, ConstructType constructType) { Asn1ClassType = Asn1Class.Universal; Asn1ConstructType = constructType; Asn1SnmpTagType = Asn1SnmpTag.NotSnmpData; Asn1TagType = asn1Tag; }
/// <summary> /// Initializes a new instance of the <see cref="Asn1TagInfo"/> struct. /// </summary> /// <param name="asn1Tag">The asn1 tag.</param> /// <param name="constructType">Type of the construct.</param> /// <param name="asn1Class">The asn1 class.</param> public Asn1TagInfo(Asn1Tag asn1Tag, ConstructType constructType, Asn1Class asn1Class) { Asn1ClassType = asn1Class; Asn1ConstructType = constructType; Asn1SnmpTagType = Asn1SnmpTag.NotSnmpData; Asn1TagType = asn1Tag; }
/// <summary> /// Writes Identifier octet of ASN.1 object. /// </summary> /// <param name="asn1Class">Class of given Asn.1 object.</param> /// <param name="tagNumber">Tag number or type of Asn.1 object.</param> /// <param name="constructed">Constructed/Primitive bit of identifier octet.</param> /// <returns>Encoded identifier octet of ASN.1 object.</returns> internal static byte[] WriteTag(Asn1Class asn1Class, int tagNumber, bool constructed = false) { byte[] tagOctets = null; var classPart = (int)asn1Class; var typePart = tagNumber & 0x1F; // clear bits 8 to 6 int tag = classPart; if (constructed) { tag = tag | 0x20; } if (asn1Class == Asn1Class.ContextSpecific && tagNumber > 30) { tag = tag + 31; // in long form bits 1-5 have value of 1 and tag number is encoded in the following octets var tagValueOctets = new List <byte>(); tagValueOctets.Add((byte)tag); DerWriterUtils.SevenBitEncode(tagNumber, tagValueOctets); tagOctets = tagValueOctets.ToArray(); } else { tag = tag + typePart; tagOctets = new byte[1] { (byte)tag }; } return(tagOctets); }
/// <summary> /// Reads one node as ASN.1 object. /// </summary> /// <typeparam name="T">Type of objects to parse. Basically it has to be Asn1BaseObject</typeparam> /// <param name="foundObject">Parsed ASN.1 Object.</param> /// <returns>Itself.</returns> public BerReader ReadOne <T>(out T foundObject) where T : Asn1ObjectBase { var nodeStartOffset = this.inputStream.Position; // get first byte - Identifier octet var firstByte = this.inputStream.ReadByte(); // break the cycle when stream ends if (firstByte == -1) { // TODO: return or throw? // end of stream foundObject = null; return(this); } // parse type of ASN.1 node Asn1Class asn1Class = ReadAsn1Class(firstByte); var constructed = (firstByte & 32) == 32; // if first byte is not enough to get ASN1 tag, we will read more from input stream int tag = ReadAsn1Tag(firstByte, this.inputStream); // read length - Length octet(s) as many as needed long length = this.ReadLength(); long substreamLength; // TODO: not sure if it's correct. Need to stop parsing because length of node greater than stream length if (length > this.inputStream.Length) { substreamLength = 0; foundObject = null; return(this); } substreamLength = length; if (length == -1) { substreamLength = this.inputStream.Length; } // read content - Value octets var contentStream = new SubStream(this.inputStream, substreamLength); // make an instance of exact ASN.1 object foundObject = MakeInstanceOfAsn1Object <T>(nodeStartOffset, asn1Class, constructed, tag, contentStream); return(this); }
/// <summary> /// Initializes a new instance of the <see cref="Asn1TagInfo"/> struct. /// </summary> /// <param name="asn1Class">The asn1 class.</param> /// <param name="constructType">Type of the construct.</param> /// <param name="tagType">Type of the tag.</param> internal Asn1TagInfo(int asn1Class, int constructType, int tagType) { Asn1ClassType = (Asn1Class)asn1Class; Asn1ConstructType = (ConstructType)constructType; if (Asn1ClassType == Asn1Class.Application) { Asn1SnmpTagType = (Asn1SnmpTag)tagType; Asn1TagType = Asn1Tag.NotAsn1Data; } else { Asn1TagType = (Asn1Tag)tagType; Asn1SnmpTagType = Asn1SnmpTag.NotSnmpData; } }
/// <summary> /// Writes Identifier octet of ASN.1 object. /// </summary> /// <param name="asn1Class">Class of given Asn.1 object.</param> /// <param name="tagNumber">Tag number or type of Asn.1 object.</param> /// <param name="constructed">Constructed/Primitive bit of identifier octet.</param> /// <returns>Encoded identifier octet of ASN.1 object.</returns> internal static byte WriteTag(Asn1Class asn1Class, int tagNumber, bool constructed = false) { // TODO: support tag number > 30 if (asn1Class == Asn1Class.ContextSpecific && tagNumber > 30) { throw new NotSupportedException("Currently only tag numbers 0-30 are supported."); } var classPart = (int)asn1Class; var typePart = tagNumber & 0x1F; // clear bits 8 to 6 int tag = classPart + typePart; if (constructed) { tag = tag | 0x20; } return((byte)tag); }
/// <summary> /// Encodes the type of the class construct. /// </summary> /// <param name="data">The data.</param> /// <param name="offset">The offset.</param> /// <param name="asn1Class">The asn1 class.</param> /// <param name="constructType">Type of the construct.</param> /// <param name="tag">The tag.</param> /// <returns>new offset value in int</returns> public static int EncodeClassConstructType(this byte[] data, int offset, Asn1Class asn1Class, ConstructType constructType, byte tag) { data[offset] = (byte)(((byte)asn1Class << 6) | ((byte)constructType << 5) | tag); return(offset + 1); }
/// <summary> /// Encodes the type of the class construct. /// </summary> /// <param name="data">The data.</param> /// <param name="offset">The offset.</param> /// <param name="asn1Class">The asn1 class.</param> /// <param name="constructType">Type of the construct.</param> /// <param name="tag">The tag.</param> /// <returns>new offset value in int</returns> public static int EncodeClassConstructType(this byte[] data, int offset, Asn1Class asn1Class, ConstructType constructType, byte tag) { data[offset] = (byte)(((byte)asn1Class << 6) | ((byte)constructType << 5) | tag); return offset + 1; }
/// <summary> /// Initializes a new instance of the <see cref="Asn1Sequence"/> class. /// </summary> /// <param name="asn1Class">Class of given Asn.1 object.</param> /// <param name="content">Content to be encoded.</param> public Asn1Sequence(Asn1Class asn1Class, List <Asn1ObjectBase> content) : base(asn1Class, true, (int)Asn1Type.Sequence, content) { }
/// <summary> /// Initializes a new instance of the <see cref="Asn1Set"/> class. /// Preferably used when reading SET. /// The encoding of a set value shall be constructed. /// </summary> /// <param name="asn1Class">Class of given Asn.1 object.</param> /// <param name="content">BER encoded value in a Stream.</param> /// <param name="constructed">Flag if type is constructed or primitive.</param> internal Asn1Set(Asn1Class asn1Class, SubStream content, bool constructed) : base(asn1Class, constructed, (int)Asn1Type.Set, content) { }
/// <summary> /// Initializes a new instance of the <see cref="Asn1Set"/> class. /// Preferably used when encoding SET. /// The encoding of a set value shall be constructed. /// </summary> /// <param name="asn1Class">Class of given Asn.1 object.</param> /// <param name="content">Content to be encoded.</param> /// <param name="constructed">Flag if type is constructed or primitive.</param> public Asn1Set(Asn1Class asn1Class, List <Asn1ObjectBase> content, bool constructed = true) : base(asn1Class, constructed, (int)Asn1Type.Set, content) { }
public Asn1TypeAttribute(Asn1Tag asn1Tag, ConstructType constructType, Asn1Class asn1Class) { this.tagInfo = new Asn1TagInfo(asn1Tag, constructType, asn1Class); }
/// <summary> /// Initializes a new instance of the <see cref="Asn1Object{T}"/> class. /// </summary> /// <param name="asn1Class">Class of given Asn.1 object.</param> /// <param name="constructed">Constructed/Primitive bit of identifier octet.</param> /// <param name="asn1Tag">Tag number or type of Asn.1 object.</param> /// <param name="content">Content to be encoded.</param> protected Asn1Object(Asn1Class asn1Class, bool constructed, int asn1Tag, T content) : base(asn1Class, constructed, asn1Tag) { this.content = content; this.toBeParsed = false; }
/// <summary> /// Initializes a new instance of the <see cref="Asn1Object{T}"/> class. /// </summary> /// <param name="asn1Class">Class of given Asn.1 object.</param> /// <param name="constructed">Constructed/Primitive bit of identifier octet.</param> /// <param name="asn1Tag">Tag number or type of Asn.1 object.</param> /// <param name="content">Content to be encoded.</param> protected Asn1Object(Asn1Class asn1Class, bool constructed, int asn1Tag, T content) : base(asn1Class, constructed, asn1Tag) { this.Content = content; }
/// <summary> /// Initializes a new instance of the <see cref="Asn1Sequence"/> class. /// Preferably used when reading SEQUENCE. /// The encoding of a sequence value shall be constructed. /// </summary> /// <param name="asn1Class">Class of given Asn.1 object.</param> /// <param name="content">BER encoded value in a Stream.</param> /// <param name="constructed">Flag if type is constructed or primitive.</param> public Asn1Sequence(Asn1Class asn1Class, SubStream content, bool constructed) : base(asn1Class, constructed, (int)Asn1Type.Sequence, content) { }
/// <summary> /// Initializes a new instance of the <see cref="Asn1ObjectBase"/> class. /// </summary> /// <param name="asn1Class">Class of given Asn.1 object.</param> /// <param name="constructed">Constructed/Primitive bit of identifier octet.</param> /// <param name="asn1Tag">Tag number or type of Asn.1 object.</param> protected Asn1ObjectBase(Asn1Class asn1Class, bool constructed, int asn1Tag) { this.Asn1Class = asn1Class; this.Constructed = constructed; this.Asn1Tag = asn1Tag; }
private static T MakeInstanceOfAsn1Object <T>(long nodeStartOffset, Asn1Class asn1Class, bool constructed, int tag, SubStream content) where T : Asn1ObjectBase { T foundObject; Asn1ObjectBase shouldBeType = null; if (asn1Class == Asn1Class.ContextSpecific) { shouldBeType = new Asn1ContextSpecific(constructed, tag, content); } else { switch ((Asn1Type)tag) { case Asn1Type.Eoc: shouldBeType = new Asn1Eoc(); break; case Asn1Type.Boolean: shouldBeType = new Asn1Boolean(content, constructed); break; case Asn1Type.Integer: shouldBeType = new Asn1Integer(content, constructed); break; case Asn1Type.BitString: shouldBeType = new Asn1BitString(content, constructed); break; case Asn1Type.OctetString: shouldBeType = new Asn1OctetString(content, constructed); break; case Asn1Type.Null: shouldBeType = new Asn1Null(constructed); break; case Asn1Type.ObjectIdentifier: shouldBeType = new Asn1ObjectIdentifier(content, constructed); break; case Asn1Type.Real: shouldBeType = new Asn1Real(content, constructed); break; case Asn1Type.Enumerated: shouldBeType = new Asn1Enumerated(content, constructed); break; case Asn1Type.Utf8String: shouldBeType = new Asn1Utf8String(content, constructed); break; case Asn1Type.RelativeOid: shouldBeType = new Asn1RelativeOid(content, constructed); break; case Asn1Type.Sequence: shouldBeType = new Asn1Sequence(asn1Class, content, constructed); break; case Asn1Type.Set: shouldBeType = new Asn1Set(asn1Class, content, constructed); break; case Asn1Type.NumericString: shouldBeType = new Asn1NumericString(content, constructed); break; case Asn1Type.PrintableString: shouldBeType = new Asn1PrintableString(content, constructed); break; case Asn1Type.T61String: shouldBeType = new Asn1T61String(content, constructed); break; case Asn1Type.Ia5String: shouldBeType = new Asn1Ia5String(content, constructed); break; case Asn1Type.UtcTime: shouldBeType = new Asn1UtcTime(content, constructed); break; case Asn1Type.GeneralizedTime: shouldBeType = new Asn1GeneralizedTime(content, constructed); break; case Asn1Type.GraphicString: shouldBeType = new Asn1GraphicString(content, constructed); break; case Asn1Type.GeneralString: shouldBeType = new Asn1GeneralString(content, constructed); break; case Asn1Type.UniversalString: shouldBeType = new Asn1UniversalString(content, constructed); break; case Asn1Type.BmpString: shouldBeType = new Asn1BmpString(content, constructed); break; case Asn1Type.ObjectDescriptor: case Asn1Type.External: case Asn1Type.EmbeddedPdv: case Asn1Type.VideotexString: case Asn1Type.VisibleString: case Asn1Type.CharacterString: case Asn1Type.LongForm: default: throw new NotSupportedException($"ASN.1 tag {tag} is unsupported."); } } foundObject = shouldBeType as T; // sanity check if (foundObject == null) { throw new FormatException(FormattableString.Invariant($"ASN.1 node at offset {nodeStartOffset} is of type {shouldBeType.GetType()} but expected type was {typeof(T)}")); } return(foundObject); }
/// <summary> /// Initializes a new instance of the <see cref="Asn1TagInfo"/> struct. /// </summary> /// <param name="asn1Class">The asn1 class.</param> /// <param name="constructType">Type of the construct.</param> /// <param name="tagType">Type of the tag.</param> internal Asn1TagInfo(int asn1Class, int constructType, int tagType) { this.Asn1ClassType = (Asn1Class)asn1Class; this.Asn1ConstructType = (ConstructType)constructType; if (this.Asn1ClassType == Asn1Class.Application) { this.Asn1SnmpTagType = (Asn1SnmpTag)tagType; this.Asn1TagType = Asn1Tag.NotAsn1Data; } else { this.Asn1TagType = (Asn1Tag)tagType; this.Asn1SnmpTagType = Asn1SnmpTag.NotSnmpData; } }