using GostCryptography.Properties; using System; using System.Collections; using System.IO; namespace GostCryptography.Asn1.Ber { public abstract class Asn1DecodeBuffer : Asn1MessageBuffer { private readonly ArrayList _captureBufferList; private int _byteCount; private Stream _inputStream; private long _markedPosition; private ArrayList _namedEventHandlerList; private int _savedByteCount; private short _typeCode; private int[] _oidBuffer; protected Asn1DecodeBuffer(byte[] msgdata) { _namedEventHandlerList = new ArrayList(); _captureBufferList = new ArrayList(5); SetInputStream(msgdata, 0, msgdata.Length); } protected Asn1DecodeBuffer(Stream inputStream) { _namedEventHandlerList = new ArrayList(); _captureBufferList = new ArrayList(5); _inputStream = inputStream.CanSeek ? inputStream : new BufferedStream(inputStream); Init(); } public virtual int ByteCount { get { return _byteCount; } } public virtual Asn1DecodeBuffer EventHandlerList { set { _namedEventHandlerList = value._namedEventHandlerList; } } public virtual short TypeCode { set { _typeCode = value; } } public virtual void AddCaptureBuffer(MemoryStream buffer) { _captureBufferList.Add(buffer); } public virtual void AddNamedEventHandler(IAsn1NamedEventHandler handler) { _namedEventHandlerList.Add(handler); } public virtual void Capture(int nbytes) { for (var i = 0; i < nbytes; i++) { var num = _inputStream.ReadByte(); if (num == -1) { throw ExceptionUtility.CryptographicException(Resources.Asn1EndOfBufferException, ByteCount); } foreach (MemoryStream s in _captureBufferList) { s.WriteByte((byte)num); } _byteCount++; } } public virtual long DecodeIntValue(int length, bool signExtend) { return Asn1RunTime.DecodeIntValue(this, length, signExtend); } public virtual int[] DecodeOidContents(int llen) { var index = 0; if (_oidBuffer == null) { _oidBuffer = new int[0x80]; } while (llen > 0) { int num; if (index >= 0x80) { throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidObjectIdException); } _oidBuffer[index] = 0; do { num = ReadByte(); _oidBuffer[index] = (_oidBuffer[index] * 0x80) + (num & 0x7f); llen--; } while ((num & 0x80) != 0); if (index == 0) { var num3 = _oidBuffer[0]; _oidBuffer[0] = ((num3 / 40) >= 2) ? 2 : (num3 / 40); _oidBuffer[1] = (_oidBuffer[0] == 2) ? (num3 - 80) : (num3 % 40); index = 2; } else { index++; } } if (llen != 0) { throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidLengthException); } var destinationArray = new int[index]; Array.Copy(_oidBuffer, 0, destinationArray, 0, index); return destinationArray; } public virtual int[] DecodeRelOidContents(int llen) { var index = 0; if (_oidBuffer == null) { _oidBuffer = new int[0x80]; } while (llen > 0) { int num; if (index >= 0x80) { throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidObjectIdException); } _oidBuffer[index] = 0; do { num = ReadByte(); _oidBuffer[index] = (_oidBuffer[index] * 0x80) + (num & 0x7f); llen--; } while ((num & 0x80) != 0); index++; } if (llen != 0) { throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidLengthException); } var destinationArray = new int[index]; Array.Copy(_oidBuffer, 0, destinationArray, 0, index); return destinationArray; } public override Stream GetInputStream() { return _inputStream; } public virtual void HexDump() { HexDump(_inputStream); } protected virtual void Init() { _byteCount = 0; _markedPosition = 0L; _savedByteCount = 0; } public virtual void InvokeCharacters(string svalue) { var enumerator = _namedEventHandlerList.GetEnumerator(); while (enumerator.MoveNext()) { ((IAsn1NamedEventHandler)enumerator.Current).Characters(svalue, _typeCode); } } public virtual void InvokeEndElement(string name, int index) { var enumerator = _namedEventHandlerList.GetEnumerator(); while (enumerator.MoveNext()) { ((IAsn1NamedEventHandler)enumerator.Current).EndElement(name, index); } } public virtual void InvokeStartElement(string name, int index) { var enumerator = _namedEventHandlerList.GetEnumerator(); while (enumerator.MoveNext()) { ((IAsn1NamedEventHandler)enumerator.Current).StartElement(name, index); } } public virtual void Mark() { _savedByteCount = _byteCount; _markedPosition = _inputStream.Position; } public virtual int Read() { var num = _inputStream.ReadByte(); if (num == -1) { throw ExceptionUtility.CryptographicException(Resources.Asn1EndOfBufferException, ByteCount); } foreach (MemoryStream s in _captureBufferList) { s.WriteByte((byte)num); } _byteCount++; return num; } public virtual void Read(byte[] buffer) { Read(buffer, 0, buffer.Length); } public virtual void Read(byte[] buffer, int offset, int nbytes) { var count = nbytes; var num3 = offset; while (count > 0) { var num = _inputStream.Read(buffer, num3, count); if (num <= 0) { throw ExceptionUtility.CryptographicException(Resources.Asn1EndOfBufferException, ByteCount); } num3 += num; count -= num; } foreach (MemoryStream s in _captureBufferList) { s.Write(buffer, offset, nbytes); } _byteCount += nbytes; } public abstract int ReadByte(); public virtual void RemoveCaptureBuffer(MemoryStream buffer) { for (var i = 0; i < _captureBufferList.Count; i++) { if (buffer == _captureBufferList[i]) { _captureBufferList.RemoveAt(i); return; } } } public virtual void Reset() { try { _inputStream.Position = _markedPosition; _byteCount = _savedByteCount; } catch (Exception) { } } public virtual void SetInputStream(byte[] msgdata, int offset, int length) { _inputStream = new MemoryStream(msgdata, offset, length); Init(); } public virtual long Skip(long nbytes) { var inputStream = _inputStream; var position = inputStream.Position; return (inputStream.Seek(nbytes, SeekOrigin.Current) - position); } } }