bool ReadByte_Tag(byte b) { if (b == 0 && _bytesRead == 0) { ResetState(DecodeState.Terminator); return(false); } if (_bytesRead > 12) { ThrowError(103, "Number of tag octets out of bounds"); } if (_bytesRead == 0 && (b & 0x1F) != 0x1F || _bytesRead > 0 && (b & 0x80) == 0) { var input = new BerMemoryInput(_buffer); if (Tag.IsZero) { // no outer tag read yet -> read outer tag var tag = BerEncoding.DecodeTag(input); if (tag.Class == BerClass.Universal) { ThrowError(107, "Universal outer tag encountered"); } if (tag.IsContainer == false) { ThrowError(108, "Primitive outer tag encountered"); } Tag = tag.ToPrimitive(); // clear container flag } else { // outer tag already read -> read inner tag (type tag) var typeTag = BerEncoding.DecodeTag(input); var type = typeTag.NumberAsType; if (BerType.IsApplicationDefined(type) == false) { if (typeTag.Class != BerClass.Universal) { ThrowError(110, "Non-universal inner tag encountered"); } if (type == 0 || type >= BerType.LastUniversal) { ThrowError(109, "Invalid BER type encountered"); } } IsContainer = typeTag.IsContainer; Type = type; } ResetState(DecodeState.Length); return(false); } _bytesRead++; return(false); }
/// <summary> /// Read the next TLTLV and publishes information like <see cref="BerLib.BerReaderBase.Tag" />, /// <see cref="BerLib.BerReaderBase.Length" />, <see cref="BerLib.BerReaderBase.Type" /> and /// <see cref="BerLib.BerReaderBase.IsContainer" />. /// Use one of the Get() functions of BerLib.BerReaderBase to retrieve the Value. /// </summary> /// <returns>True if a valid TLTLV has been read, otherwise false.</returns> public bool Read() { Debug.Assert(_input != null); var typeTag = BerTag.Zero; DisposeCurrentTlv(); if (_parentReader != null && // non top-level read? this.Eof) { HandleEof(); return(false); } Tag = BerEncoding.DecodeTag(this); if (Tag.IsZero) { // terminator of indefinite length field: 4 zeros (outer length AND inner length must be indefinite if (ReadByte() == 0 && ReadByte() == 0 && ReadByte() == 0) { HandleEof(); return(false); } else { ThrowError(10, "Invalid zero tag: 0x00"); } } OuterLength = BerEncoding.DecodeLength(this); if (OuterLength == 0) { ThrowError(13, "Zero outer length encountered"); } if (Tag.IsContainer && Tag.Class != BerClass.Universal) { typeTag = BerEncoding.DecodeTag(this); Length = BerEncoding.DecodeLength(this); if ((Length == BerDefinitions.IndefiniteLength) != (OuterLength == BerDefinitions.IndefiniteLength)) { ThrowError(12, "Outer and inner tag must use the same length form"); } } else { ThrowError(14, "Implicit tag or universal outer tag found"); } IsContainer = typeTag.IsContainer; Tag = Tag.ToPrimitive(); // clear container flag Type = typeTag.NumberAsType; if (Length == BerDefinitions.IndefiniteLength && IsContainer == false) { ThrowError(11, "Indefinite length form is only allowed on containers"); } if (IsContainer == false && Length > 0) { var value = new byte[Length]; for (int index = 0; index < Length; index++) { value[index] = ReadByte(); } Value = value; } return(true); }