From 44288db4414158ac9b98a507b15e81d0d3c66ca6 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 28 Jun 2013 15:26:06 +0700 Subject: Initial import of old CVS repository --- crypto/src/asn1/util/Asn1Dump.cs | 378 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 crypto/src/asn1/util/Asn1Dump.cs (limited to 'crypto/src/asn1/util/Asn1Dump.cs') diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs new file mode 100644 index 000000000..43d485500 --- /dev/null +++ b/crypto/src/asn1/util/Asn1Dump.cs @@ -0,0 +1,378 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Asn1.Utilities +{ + public sealed class Asn1Dump + { + private static readonly string NewLine = Platform.NewLine; + + private Asn1Dump() + { + } + + private const string Tab = " "; + private const int SampleSize = 32; + + /** + * dump a Der object as a formatted string with indentation + * + * @param obj the Asn1Object to be dumped out. + */ + private static void AsString( + string indent, + bool verbose, + Asn1Object obj, + StringBuilder buf) + { + if (obj is Asn1Sequence) + { + string tab = indent + Tab; + buf.Append(indent); + if (obj is BerSequence) + { + buf.Append("BER Sequence"); + } + else if (obj is DerSequence) + { + buf.Append("DER Sequence"); + } + else + { + buf.Append("Sequence"); + } + + buf.Append(NewLine); + + foreach (Asn1Encodable o in ((Asn1Sequence)obj)) + { + if (o == null || o is Asn1Null) + { + buf.Append(tab); + buf.Append("NULL"); + buf.Append(NewLine); + } + else + { + AsString(tab, verbose, o.ToAsn1Object(), buf); + } + } + } + else if (obj is DerTaggedObject) + { + string tab = indent + Tab; + buf.Append(indent); + if (obj is BerTaggedObject) + { + buf.Append("BER Tagged ["); + } + else + { + buf.Append("Tagged ["); + } + + DerTaggedObject o = (DerTaggedObject)obj; + + buf.Append(((int)o.TagNo).ToString()); + buf.Append(']'); + + if (!o.IsExplicit()) + { + buf.Append(" IMPLICIT "); + } + + buf.Append(NewLine); + + if (o.IsEmpty()) + { + buf.Append(tab); + buf.Append("EMPTY"); + buf.Append(NewLine); + } + else + { + AsString(tab, verbose, o.GetObject(), buf); + } + } + else if (obj is BerSet) + { + string tab = indent + Tab; + + buf.Append(indent); + buf.Append("BER Set"); + buf.Append(NewLine); + + foreach (Asn1Encodable o in ((Asn1Set)obj)) + { + if (o == null) + { + buf.Append(tab); + buf.Append("NULL"); + buf.Append(NewLine); + } + else + { + AsString(tab, verbose, o.ToAsn1Object(), buf); + } + } + } + else if (obj is DerSet) + { + string tab = indent + Tab; + + buf.Append(indent); + buf.Append("DER Set"); + buf.Append(NewLine); + + foreach (Asn1Encodable o in ((Asn1Set)obj)) + { + if (o == null) + { + buf.Append(tab); + buf.Append("NULL"); + buf.Append(NewLine); + } + else + { + AsString(tab, verbose, o.ToAsn1Object(), buf); + } + } + } + else if (obj is DerObjectIdentifier) + { + buf.Append(indent + "ObjectIdentifier(" + ((DerObjectIdentifier)obj).Id + ")" + NewLine); + } + else if (obj is DerBoolean) + { + buf.Append(indent + "Boolean(" + ((DerBoolean)obj).IsTrue + ")" + NewLine); + } + else if (obj is DerInteger) + { + buf.Append(indent + "Integer(" + ((DerInteger)obj).Value + ")" + NewLine); + } + else if (obj is BerOctetString) + { + byte[] octets = ((Asn1OctetString)obj).GetOctets(); + string extra = verbose ? dumpBinaryDataAsString(indent, octets) : ""; + buf.Append(indent + "BER Octet String" + "[" + octets.Length + "] " + extra + NewLine); + } + else if (obj is DerOctetString) + { + byte[] octets = ((Asn1OctetString)obj).GetOctets(); + string extra = verbose ? dumpBinaryDataAsString(indent, octets) : ""; + buf.Append(indent + "DER Octet String" + "[" + octets.Length + "] " + extra + NewLine); + } + else if (obj is DerBitString) + { + DerBitString bt = (DerBitString)obj; + byte[] bytes = bt.GetBytes(); + string extra = verbose ? dumpBinaryDataAsString(indent, bytes) : ""; + buf.Append(indent + "DER Bit String" + "[" + bytes.Length + ", " + bt.PadBits + "] " + extra + NewLine); + } + else if (obj is DerIA5String) + { + buf.Append(indent + "IA5String(" + ((DerIA5String)obj).GetString() + ") " + NewLine); + } + else if (obj is DerUtf8String) + { + buf.Append(indent + "UTF8String(" + ((DerUtf8String)obj).GetString() + ") " + NewLine); + } + else if (obj is DerPrintableString) + { + buf.Append(indent + "PrintableString(" + ((DerPrintableString)obj).GetString() + ") " + NewLine); + } + else if (obj is DerVisibleString) + { + buf.Append(indent + "VisibleString(" + ((DerVisibleString)obj).GetString() + ") " + NewLine); + } + else if (obj is DerBmpString) + { + buf.Append(indent + "BMPString(" + ((DerBmpString)obj).GetString() + ") " + NewLine); + } + else if (obj is DerT61String) + { + buf.Append(indent + "T61String(" + ((DerT61String)obj).GetString() + ") " + NewLine); + } + else if (obj is DerUtcTime) + { + buf.Append(indent + "UTCTime(" + ((DerUtcTime)obj).TimeString + ") " + NewLine); + } + else if (obj is DerGeneralizedTime) + { + buf.Append(indent + "GeneralizedTime(" + ((DerGeneralizedTime)obj).GetTime() + ") " + NewLine); + } + else if (obj is DerUnknownTag) + { + string hex = Hex.ToHexString(((DerUnknownTag)obj).GetData()); + buf.Append(indent + "Unknown " + ((int)((DerUnknownTag)obj).Tag).ToString("X") + " " + hex + NewLine); + } + else if (obj is BerApplicationSpecific) + { + buf.Append(outputApplicationSpecific("BER", indent, verbose, (BerApplicationSpecific)obj)); + } + else if (obj is DerApplicationSpecific) + { + buf.Append(outputApplicationSpecific("DER", indent, verbose, (DerApplicationSpecific)obj)); + } + else if (obj is DerEnumerated) + { + DerEnumerated en = (DerEnumerated)obj; + buf.Append(indent + "DER Enumerated(" + en.Value + ")" + NewLine); + } + else if (obj is DerExternal) + { + DerExternal ext = (DerExternal)obj; + buf.Append(indent + "External " + NewLine); + string tab = indent + Tab; + + if (ext.DirectReference != null) + { + buf.Append(tab + "Direct Reference: " + ext.DirectReference.Id + NewLine); + } + if (ext.IndirectReference != null) + { + buf.Append(tab + "Indirect Reference: " + ext.IndirectReference.ToString() + NewLine); + } + if (ext.DataValueDescriptor != null) + { + AsString(tab, verbose, ext.DataValueDescriptor, buf); + } + buf.Append(tab + "Encoding: " + ext.Encoding + NewLine); + AsString(tab, verbose, ext.ExternalContent, buf); + } + else + { + buf.Append(indent + obj.ToString() + NewLine); + } + } + + private static string outputApplicationSpecific( + string type, + string indent, + bool verbose, + DerApplicationSpecific app) + { + StringBuilder buf = new StringBuilder(); + + if (app.IsConstructed()) + { + try + { + Asn1Sequence s = Asn1Sequence.GetInstance(app.GetObject(Asn1Tags.Sequence)); + buf.Append(indent + type + " ApplicationSpecific[" + app.ApplicationTag + "]" + NewLine); + foreach (Asn1Encodable ae in s) + { + AsString(indent + Tab, verbose, ae.ToAsn1Object(), buf); + } + } + catch (IOException e) + { + buf.Append(e); + } + return buf.ToString(); + } + + return indent + type + " ApplicationSpecific[" + app.ApplicationTag + "] (" + + Hex.ToHexString(app.GetContents()) + ")" + NewLine; + } + + [Obsolete("Use version accepting Asn1Encodable")] + public static string DumpAsString( + object obj) + { + if (obj is Asn1Encodable) + { + StringBuilder buf = new StringBuilder(); + AsString("", false, ((Asn1Encodable)obj).ToAsn1Object(), buf); + return buf.ToString(); + } + + return "unknown object type " + obj.ToString(); + } + + /** + * dump out a DER object as a formatted string, in non-verbose mode + * + * @param obj the Asn1Encodable to be dumped out. + * @return the resulting string. + */ + public static string DumpAsString( + Asn1Encodable obj) + { + return DumpAsString(obj, false); + } + + /** + * Dump out the object as a string + * + * @param obj the Asn1Encodable to be dumped out. + * @param verbose if true, dump out the contents of octet and bit strings. + * @return the resulting string. + */ + public static string DumpAsString( + Asn1Encodable obj, + bool verbose) + { + StringBuilder buf = new StringBuilder(); + AsString("", verbose, obj.ToAsn1Object(), buf); + return buf.ToString(); + } + + private static string dumpBinaryDataAsString(string indent, byte[] bytes) + { + indent += Tab; + + StringBuilder buf = new StringBuilder(NewLine); + + for (int i = 0; i < bytes.Length; i += SampleSize) + { + if (bytes.Length - i > SampleSize) + { + buf.Append(indent); + buf.Append(Hex.ToHexString(bytes, i, SampleSize)); + buf.Append(Tab); + buf.Append(calculateAscString(bytes, i, SampleSize)); + buf.Append(NewLine); + } + else + { + buf.Append(indent); + buf.Append(Hex.ToHexString(bytes, i, bytes.Length - i)); + for (int j = bytes.Length - i; j != SampleSize; j++) + { + buf.Append(" "); + } + buf.Append(Tab); + buf.Append(calculateAscString(bytes, i, bytes.Length - i)); + buf.Append(NewLine); + } + } + + return buf.ToString(); + } + + private static string calculateAscString( + byte[] bytes, + int off, + int len) + { + StringBuilder buf = new StringBuilder(); + + for (int i = off; i != off + len; i++) + { + char c = (char)bytes[i]; + if (c >= ' ' && c <= '~') + { + buf.Append(c); + } + } + + return buf.ToString(); + } + } +} -- cgit 1.4.1 From e881ee06950d623a7678cda637ebd39dd33658fa Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 21 Jan 2014 19:43:45 +0700 Subject: Stop using DerUnknownTag (throw exceptions during parsing instead) --- crypto/src/asn1/ASN1StreamParser.cs | 5 +- crypto/src/asn1/Asn1InputStream.cs | 626 ++++++++++----------- crypto/src/asn1/util/Asn1Dump.cs | 289 +++++----- crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs | 1 - 4 files changed, 457 insertions(+), 464 deletions(-) (limited to 'crypto/src/asn1/util/Asn1Dump.cs') diff --git a/crypto/src/asn1/ASN1StreamParser.cs b/crypto/src/asn1/ASN1StreamParser.cs index a5e6e3164..0c6b4413a 100644 --- a/crypto/src/asn1/ASN1StreamParser.cs +++ b/crypto/src/asn1/ASN1StreamParser.cs @@ -187,9 +187,8 @@ namespace Org.BouncyCastle.Asn1 case Asn1Tags.External: return new DerExternalParser(new Asn1StreamParser(defIn)); default: - // TODO Add DerUnknownTagParser class? - return new DerUnknownTag(true, tagNo, defIn.ToArray()); - } + throw new IOException("unknown tag " + tagNo + " encountered"); + } } // Some primitive encodings can be handled by parsers too... diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs index 5d5590655..18d13c32d 100644 --- a/crypto/src/asn1/Asn1InputStream.cs +++ b/crypto/src/asn1/Asn1InputStream.cs @@ -7,290 +7,290 @@ using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Asn1 { - /** - * a general purpose ASN.1 decoder - note: this class differs from the - * others in that it returns null after it has read the last object in - * the stream. If an ASN.1 Null is encountered a Der/BER Null object is - * returned. - */ - public class Asn1InputStream - : FilterStream - { - private readonly int limit; + /** + * a general purpose ASN.1 decoder - note: this class differs from the + * others in that it returns null after it has read the last object in + * the stream. If an ASN.1 Null is encountered a Der/BER Null object is + * returned. + */ + public class Asn1InputStream + : FilterStream + { + private readonly int limit; private readonly byte[][] tmpBuffers; internal static int FindLimit(Stream input) - { - if (input is LimitedInputStream) - { - return ((LimitedInputStream)input).GetRemaining(); - } - else if (input is MemoryStream) - { - MemoryStream mem = (MemoryStream)input; - return (int)(mem.Length - mem.Position); - } - - return int.MaxValue; - } - - public Asn1InputStream( - Stream inputStream) - : this(inputStream, FindLimit(inputStream)) - { - } - - /** - * Create an ASN1InputStream where no DER object will be longer than limit. - * - * @param input stream containing ASN.1 encoded data. - * @param limit maximum size of a DER encoded object. - */ - public Asn1InputStream( - Stream inputStream, - int limit) - : base(inputStream) - { - this.limit = limit; + { + if (input is LimitedInputStream) + { + return ((LimitedInputStream)input).GetRemaining(); + } + else if (input is MemoryStream) + { + MemoryStream mem = (MemoryStream)input; + return (int)(mem.Length - mem.Position); + } + + return int.MaxValue; + } + + public Asn1InputStream( + Stream inputStream) + : this(inputStream, FindLimit(inputStream)) + { + } + + /** + * Create an ASN1InputStream where no DER object will be longer than limit. + * + * @param input stream containing ASN.1 encoded data. + * @param limit maximum size of a DER encoded object. + */ + public Asn1InputStream( + Stream inputStream, + int limit) + : base(inputStream) + { + this.limit = limit; this.tmpBuffers = new byte[16][]; } - /** - * Create an ASN1InputStream based on the input byte array. The length of DER objects in - * the stream is automatically limited to the length of the input array. - * - * @param input array containing ASN.1 encoded data. - */ - public Asn1InputStream( - byte[] input) - : this(new MemoryStream(input, false), input.Length) - { - } - - /** - * build an object given its tag and the number of bytes to construct it from. - */ - private Asn1Object BuildObject( - int tag, - int tagNo, - int length) - { - bool isConstructed = (tag & Asn1Tags.Constructed) != 0; - - DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length); - - if ((tag & Asn1Tags.Application) != 0) - { - return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray()); - } - - if ((tag & Asn1Tags.Tagged) != 0) - { - return new Asn1StreamParser(defIn).ReadTaggedObject(isConstructed, tagNo); - } - - if (isConstructed) - { - // TODO There are other tags that may be constructed (e.g. BitString) - switch (tagNo) - { - case Asn1Tags.OctetString: - // - // yes, people actually do this... - // - return new BerOctetString(BuildDerEncodableVector(defIn)); - case Asn1Tags.Sequence: - return CreateDerSequence(defIn); - case Asn1Tags.Set: - return CreateDerSet(defIn); - case Asn1Tags.External: - return new DerExternal(BuildDerEncodableVector(defIn)); - default: - return new DerUnknownTag(true, tagNo, defIn.ToArray()); - } - } + /** + * Create an ASN1InputStream based on the input byte array. The length of DER objects in + * the stream is automatically limited to the length of the input array. + * + * @param input array containing ASN.1 encoded data. + */ + public Asn1InputStream( + byte[] input) + : this(new MemoryStream(input, false), input.Length) + { + } + + /** + * build an object given its tag and the number of bytes to construct it from. + */ + private Asn1Object BuildObject( + int tag, + int tagNo, + int length) + { + bool isConstructed = (tag & Asn1Tags.Constructed) != 0; + + DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length); + + if ((tag & Asn1Tags.Application) != 0) + { + return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray()); + } + + if ((tag & Asn1Tags.Tagged) != 0) + { + return new Asn1StreamParser(defIn).ReadTaggedObject(isConstructed, tagNo); + } + + if (isConstructed) + { + // TODO There are other tags that may be constructed (e.g. BitString) + switch (tagNo) + { + case Asn1Tags.OctetString: + // + // yes, people actually do this... + // + return new BerOctetString(BuildDerEncodableVector(defIn)); + case Asn1Tags.Sequence: + return CreateDerSequence(defIn); + case Asn1Tags.Set: + return CreateDerSet(defIn); + case Asn1Tags.External: + return new DerExternal(BuildDerEncodableVector(defIn)); + default: + throw new IOException("unknown tag " + tagNo + " encountered"); + } + } return CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers); - } + } internal Asn1EncodableVector BuildEncodableVector() - { - Asn1EncodableVector v = new Asn1EncodableVector(); - - Asn1Object o; - while ((o = ReadObject()) != null) - { - v.Add(o); - } - - return v; - } - - internal virtual Asn1EncodableVector BuildDerEncodableVector( - DefiniteLengthInputStream dIn) - { - return new Asn1InputStream(dIn).BuildEncodableVector(); - } - - internal virtual DerSequence CreateDerSequence( - DefiniteLengthInputStream dIn) - { - return DerSequence.FromVector(BuildDerEncodableVector(dIn)); - } - - internal virtual DerSet CreateDerSet( - DefiniteLengthInputStream dIn) - { - return DerSet.FromVector(BuildDerEncodableVector(dIn), false); - } - - public Asn1Object ReadObject() - { - int tag = ReadByte(); - if (tag <= 0) - { - if (tag == 0) - throw new IOException("unexpected end-of-contents marker"); - - return null; - } - - // - // calculate tag number - // - int tagNo = ReadTagNumber(this.s, tag); - - bool isConstructed = (tag & Asn1Tags.Constructed) != 0; - - // - // calculate length - // - int length = ReadLength(this.s, limit); - - if (length < 0) // indefinite length method - { - if (!isConstructed) - throw new IOException("indefinite length primitive encoding encountered"); - - IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit); - Asn1StreamParser sp = new Asn1StreamParser(indIn, limit); - - if ((tag & Asn1Tags.Application) != 0) - { - return new BerApplicationSpecificParser(tagNo, sp).ToAsn1Object(); - } - - if ((tag & Asn1Tags.Tagged) != 0) - { - return new BerTaggedObjectParser(true, tagNo, sp).ToAsn1Object(); - } - - // TODO There are other tags that may be constructed (e.g. BitString) - switch (tagNo) - { - case Asn1Tags.OctetString: - return new BerOctetStringParser(sp).ToAsn1Object(); - case Asn1Tags.Sequence: - return new BerSequenceParser(sp).ToAsn1Object(); - case Asn1Tags.Set: - return new BerSetParser(sp).ToAsn1Object(); - case Asn1Tags.External: - return new DerExternalParser(sp).ToAsn1Object(); - default: - throw new IOException("unknown BER object encountered"); - } - } - else - { - try - { - return BuildObject(tag, tagNo, length); - } - catch (ArgumentException e) - { - throw new Asn1Exception("corrupted stream detected", e); - } - } - } - - internal static int ReadTagNumber( - Stream s, - int tag) - { - int tagNo = tag & 0x1f; - - // - // with tagged object tag number is bottom 5 bits, or stored at the start of the content - // - if (tagNo == 0x1f) - { - tagNo = 0; - - int b = s.ReadByte(); - - // X.690-0207 8.1.2.4.2 - // "c) bits 7 to 1 of the first subsequent octet shall not all be zero." - if ((b & 0x7f) == 0) // Note: -1 will pass - { - throw new IOException("Corrupted stream - invalid high tag number found"); - } - - while ((b >= 0) && ((b & 0x80) != 0)) - { - tagNo |= (b & 0x7f); - tagNo <<= 7; - b = s.ReadByte(); - } - - if (b < 0) - throw new EndOfStreamException("EOF found inside tag value."); - - tagNo |= (b & 0x7f); - } - - return tagNo; - } - - internal static int ReadLength( - Stream s, - int limit) - { - int length = s.ReadByte(); - if (length < 0) - throw new EndOfStreamException("EOF found when length expected"); - - if (length == 0x80) - return -1; // indefinite-length encoding - - if (length > 127) - { - int size = length & 0x7f; - - // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here - if (size > 4) - throw new IOException("DER length more than 4 bytes: " + size); - - length = 0; - for (int i = 0; i < size; i++) - { - int next = s.ReadByte(); - - if (next < 0) - throw new EndOfStreamException("EOF found reading length"); - - length = (length << 8) + next; - } - - if (length < 0) - throw new IOException("Corrupted stream - negative length found"); - - if (length >= limit) // after all we must have read at least 1 byte - throw new IOException("Corrupted stream - out of bounds length found"); - } - - return length; - } + { + Asn1EncodableVector v = new Asn1EncodableVector(); + + Asn1Object o; + while ((o = ReadObject()) != null) + { + v.Add(o); + } + + return v; + } + + internal virtual Asn1EncodableVector BuildDerEncodableVector( + DefiniteLengthInputStream dIn) + { + return new Asn1InputStream(dIn).BuildEncodableVector(); + } + + internal virtual DerSequence CreateDerSequence( + DefiniteLengthInputStream dIn) + { + return DerSequence.FromVector(BuildDerEncodableVector(dIn)); + } + + internal virtual DerSet CreateDerSet( + DefiniteLengthInputStream dIn) + { + return DerSet.FromVector(BuildDerEncodableVector(dIn), false); + } + + public Asn1Object ReadObject() + { + int tag = ReadByte(); + if (tag <= 0) + { + if (tag == 0) + throw new IOException("unexpected end-of-contents marker"); + + return null; + } + + // + // calculate tag number + // + int tagNo = ReadTagNumber(this.s, tag); + + bool isConstructed = (tag & Asn1Tags.Constructed) != 0; + + // + // calculate length + // + int length = ReadLength(this.s, limit); + + if (length < 0) // indefinite length method + { + if (!isConstructed) + throw new IOException("indefinite length primitive encoding encountered"); + + IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit); + Asn1StreamParser sp = new Asn1StreamParser(indIn, limit); + + if ((tag & Asn1Tags.Application) != 0) + { + return new BerApplicationSpecificParser(tagNo, sp).ToAsn1Object(); + } + + if ((tag & Asn1Tags.Tagged) != 0) + { + return new BerTaggedObjectParser(true, tagNo, sp).ToAsn1Object(); + } + + // TODO There are other tags that may be constructed (e.g. BitString) + switch (tagNo) + { + case Asn1Tags.OctetString: + return new BerOctetStringParser(sp).ToAsn1Object(); + case Asn1Tags.Sequence: + return new BerSequenceParser(sp).ToAsn1Object(); + case Asn1Tags.Set: + return new BerSetParser(sp).ToAsn1Object(); + case Asn1Tags.External: + return new DerExternalParser(sp).ToAsn1Object(); + default: + throw new IOException("unknown BER object encountered"); + } + } + else + { + try + { + return BuildObject(tag, tagNo, length); + } + catch (ArgumentException e) + { + throw new Asn1Exception("corrupted stream detected", e); + } + } + } + + internal static int ReadTagNumber( + Stream s, + int tag) + { + int tagNo = tag & 0x1f; + + // + // with tagged object tag number is bottom 5 bits, or stored at the start of the content + // + if (tagNo == 0x1f) + { + tagNo = 0; + + int b = s.ReadByte(); + + // X.690-0207 8.1.2.4.2 + // "c) bits 7 to 1 of the first subsequent octet shall not all be zero." + if ((b & 0x7f) == 0) // Note: -1 will pass + { + throw new IOException("Corrupted stream - invalid high tag number found"); + } + + while ((b >= 0) && ((b & 0x80) != 0)) + { + tagNo |= (b & 0x7f); + tagNo <<= 7; + b = s.ReadByte(); + } + + if (b < 0) + throw new EndOfStreamException("EOF found inside tag value."); + + tagNo |= (b & 0x7f); + } + + return tagNo; + } + + internal static int ReadLength( + Stream s, + int limit) + { + int length = s.ReadByte(); + if (length < 0) + throw new EndOfStreamException("EOF found when length expected"); + + if (length == 0x80) + return -1; // indefinite-length encoding + + if (length > 127) + { + int size = length & 0x7f; + + // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here + if (size > 4) + throw new IOException("DER length more than 4 bytes: " + size); + + length = 0; + for (int i = 0; i < size; i++) + { + int next = s.ReadByte(); + + if (next < 0) + throw new EndOfStreamException("EOF found reading length"); + + length = (length << 8) + next; + } + + if (length < 0) + throw new IOException("Corrupted stream - negative length found"); + + if (length >= limit) // after all we must have read at least 1 byte + throw new IOException("Corrupted stream - out of bounds length found"); + } + + return length; + } internal static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers) { @@ -311,11 +311,11 @@ namespace Org.BouncyCastle.Asn1 return buf; } - internal static Asn1Object CreatePrimitiveDerObject( - int tagNo, - DefiniteLengthInputStream defIn, + internal static Asn1Object CreatePrimitiveDerObject( + int tagNo, + DefiniteLengthInputStream defIn, byte[][] tmpBuffers) - { + { switch (tagNo) { case Asn1Tags.Boolean: @@ -329,40 +329,40 @@ namespace Org.BouncyCastle.Asn1 byte[] bytes = defIn.ToArray(); switch (tagNo) - { - case Asn1Tags.BitString: - return DerBitString.FromAsn1Octets(bytes); - case Asn1Tags.BmpString: - return new DerBmpString(bytes); - case Asn1Tags.GeneralizedTime: - return new DerGeneralizedTime(bytes); - case Asn1Tags.GeneralString: - return new DerGeneralString(bytes); - case Asn1Tags.IA5String: - return new DerIA5String(bytes); - case Asn1Tags.Integer: - return new DerInteger(bytes); - case Asn1Tags.Null: - return DerNull.Instance; // actual content is ignored (enforce 0 length?) - case Asn1Tags.NumericString: - return new DerNumericString(bytes); - case Asn1Tags.OctetString: - return new DerOctetString(bytes); - case Asn1Tags.PrintableString: - return new DerPrintableString(bytes); - case Asn1Tags.T61String: - return new DerT61String(bytes); - case Asn1Tags.UniversalString: - return new DerUniversalString(bytes); - case Asn1Tags.UtcTime: - return new DerUtcTime(bytes); - case Asn1Tags.Utf8String: - return new DerUtf8String(bytes); - case Asn1Tags.VisibleString: - return new DerVisibleString(bytes); - default: - return new DerUnknownTag(false, tagNo, bytes); - } - } - } + { + case Asn1Tags.BitString: + return DerBitString.FromAsn1Octets(bytes); + case Asn1Tags.BmpString: + return new DerBmpString(bytes); + case Asn1Tags.GeneralizedTime: + return new DerGeneralizedTime(bytes); + case Asn1Tags.GeneralString: + return new DerGeneralString(bytes); + case Asn1Tags.IA5String: + return new DerIA5String(bytes); + case Asn1Tags.Integer: + return new DerInteger(bytes); + case Asn1Tags.Null: + return DerNull.Instance; // actual content is ignored (enforce 0 length?) + case Asn1Tags.NumericString: + return new DerNumericString(bytes); + case Asn1Tags.OctetString: + return new DerOctetString(bytes); + case Asn1Tags.PrintableString: + return new DerPrintableString(bytes); + case Asn1Tags.T61String: + return new DerT61String(bytes); + case Asn1Tags.UniversalString: + return new DerUniversalString(bytes); + case Asn1Tags.UtcTime: + return new DerUtcTime(bytes); + case Asn1Tags.Utf8String: + return new DerUtf8String(bytes); + case Asn1Tags.VisibleString: + return new DerVisibleString(bytes); + default: + throw new IOException("unknown tag " + tagNo + " encountered"); + } + } + } } diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs index 43d485500..36b17c8fd 100644 --- a/crypto/src/asn1/util/Asn1Dump.cs +++ b/crypto/src/asn1/util/Asn1Dump.cs @@ -10,9 +10,9 @@ namespace Org.BouncyCastle.Asn1.Utilities { public sealed class Asn1Dump { - private static readonly string NewLine = Platform.NewLine; + private static readonly string NewLine = Platform.NewLine; - private Asn1Dump() + private Asn1Dump() { } @@ -28,12 +28,12 @@ namespace Org.BouncyCastle.Asn1.Utilities string indent, bool verbose, Asn1Object obj, - StringBuilder buf) + StringBuilder buf) { if (obj is Asn1Sequence) { - string tab = indent + Tab; - buf.Append(indent); + string tab = indent + Tab; + buf.Append(indent); if (obj is BerSequence) { buf.Append("BER Sequence"); @@ -49,8 +49,8 @@ namespace Org.BouncyCastle.Asn1.Utilities buf.Append(NewLine); - foreach (Asn1Encodable o in ((Asn1Sequence)obj)) - { + foreach (Asn1Encodable o in ((Asn1Sequence)obj)) + { if (o == null || o is Asn1Null) { buf.Append(tab); @@ -66,7 +66,7 @@ namespace Org.BouncyCastle.Asn1.Utilities else if (obj is DerTaggedObject) { string tab = indent + Tab; - buf.Append(indent); + buf.Append(indent); if (obj is BerTaggedObject) { buf.Append("BER Tagged ["); @@ -76,19 +76,19 @@ namespace Org.BouncyCastle.Asn1.Utilities buf.Append("Tagged ["); } - DerTaggedObject o = (DerTaggedObject)obj; + DerTaggedObject o = (DerTaggedObject)obj; - buf.Append(((int)o.TagNo).ToString()); + buf.Append(((int)o.TagNo).ToString()); buf.Append(']'); - if (!o.IsExplicit()) + if (!o.IsExplicit()) { buf.Append(" IMPLICIT "); } - buf.Append(NewLine); + buf.Append(NewLine); - if (o.IsEmpty()) + if (o.IsEmpty()) { buf.Append(tab); buf.Append("EMPTY"); @@ -103,12 +103,12 @@ namespace Org.BouncyCastle.Asn1.Utilities { string tab = indent + Tab; - buf.Append(indent); + buf.Append(indent); buf.Append("BER Set"); buf.Append(NewLine); - foreach (Asn1Encodable o in ((Asn1Set)obj)) - { + foreach (Asn1Encodable o in ((Asn1Set)obj)) + { if (o == null) { buf.Append(tab); @@ -125,12 +125,12 @@ namespace Org.BouncyCastle.Asn1.Utilities { string tab = indent + Tab; - buf.Append(indent); + buf.Append(indent); buf.Append("DER Set"); buf.Append(NewLine); - foreach (Asn1Encodable o in ((Asn1Set)obj)) - { + foreach (Asn1Encodable o in ((Asn1Set)obj)) + { if (o == null) { buf.Append(tab); @@ -155,33 +155,33 @@ namespace Org.BouncyCastle.Asn1.Utilities { buf.Append(indent + "Integer(" + ((DerInteger)obj).Value + ")" + NewLine); } - else if (obj is BerOctetString) - { - byte[] octets = ((Asn1OctetString)obj).GetOctets(); - string extra = verbose ? dumpBinaryDataAsString(indent, octets) : ""; - buf.Append(indent + "BER Octet String" + "[" + octets.Length + "] " + extra + NewLine); - } + else if (obj is BerOctetString) + { + byte[] octets = ((Asn1OctetString)obj).GetOctets(); + string extra = verbose ? dumpBinaryDataAsString(indent, octets) : ""; + buf.Append(indent + "BER Octet String" + "[" + octets.Length + "] " + extra + NewLine); + } else if (obj is DerOctetString) { - byte[] octets = ((Asn1OctetString)obj).GetOctets(); - string extra = verbose ? dumpBinaryDataAsString(indent, octets) : ""; - buf.Append(indent + "DER Octet String" + "[" + octets.Length + "] " + extra + NewLine); - } - else if (obj is DerBitString) - { - DerBitString bt = (DerBitString)obj; - byte[] bytes = bt.GetBytes(); - string extra = verbose ? dumpBinaryDataAsString(indent, bytes) : ""; - buf.Append(indent + "DER Bit String" + "[" + bytes.Length + ", " + bt.PadBits + "] " + extra + NewLine); - } + byte[] octets = ((Asn1OctetString)obj).GetOctets(); + string extra = verbose ? dumpBinaryDataAsString(indent, octets) : ""; + buf.Append(indent + "DER Octet String" + "[" + octets.Length + "] " + extra + NewLine); + } + else if (obj is DerBitString) + { + DerBitString bt = (DerBitString)obj; + byte[] bytes = bt.GetBytes(); + string extra = verbose ? dumpBinaryDataAsString(indent, bytes) : ""; + buf.Append(indent + "DER Bit String" + "[" + bytes.Length + ", " + bt.PadBits + "] " + extra + NewLine); + } else if (obj is DerIA5String) { buf.Append(indent + "IA5String(" + ((DerIA5String)obj).GetString() + ") " + NewLine); } - else if (obj is DerUtf8String) - { - buf.Append(indent + "UTF8String(" + ((DerUtf8String)obj).GetString() + ") " + NewLine); - } + else if (obj is DerUtf8String) + { + buf.Append(indent + "UTF8String(" + ((DerUtf8String)obj).GetString() + ") " + NewLine); + } else if (obj is DerPrintableString) { buf.Append(indent + "PrintableString(" + ((DerPrintableString)obj).GetString() + ") " + NewLine); @@ -202,14 +202,9 @@ namespace Org.BouncyCastle.Asn1.Utilities { buf.Append(indent + "UTCTime(" + ((DerUtcTime)obj).TimeString + ") " + NewLine); } - else if (obj is DerGeneralizedTime) - { - buf.Append(indent + "GeneralizedTime(" + ((DerGeneralizedTime)obj).GetTime() + ") " + NewLine); - } - else if (obj is DerUnknownTag) + else if (obj is DerGeneralizedTime) { - string hex = Hex.ToHexString(((DerUnknownTag)obj).GetData()); - buf.Append(indent + "Unknown " + ((int)((DerUnknownTag)obj).Tag).ToString("X") + " " + hex + NewLine); + buf.Append(indent + "GeneralizedTime(" + ((DerGeneralizedTime)obj).GetTime() + ") " + NewLine); } else if (obj is BerApplicationSpecific) { @@ -219,32 +214,32 @@ namespace Org.BouncyCastle.Asn1.Utilities { buf.Append(outputApplicationSpecific("DER", indent, verbose, (DerApplicationSpecific)obj)); } - else if (obj is DerEnumerated) - { - DerEnumerated en = (DerEnumerated)obj; - buf.Append(indent + "DER Enumerated(" + en.Value + ")" + NewLine); - } - else if (obj is DerExternal) - { - DerExternal ext = (DerExternal)obj; - buf.Append(indent + "External " + NewLine); + else if (obj is DerEnumerated) + { + DerEnumerated en = (DerEnumerated)obj; + buf.Append(indent + "DER Enumerated(" + en.Value + ")" + NewLine); + } + else if (obj is DerExternal) + { + DerExternal ext = (DerExternal)obj; + buf.Append(indent + "External " + NewLine); string tab = indent + Tab; - if (ext.DirectReference != null) - { - buf.Append(tab + "Direct Reference: " + ext.DirectReference.Id + NewLine); - } - if (ext.IndirectReference != null) - { - buf.Append(tab + "Indirect Reference: " + ext.IndirectReference.ToString() + NewLine); - } - if (ext.DataValueDescriptor != null) - { - AsString(tab, verbose, ext.DataValueDescriptor, buf); - } - buf.Append(tab + "Encoding: " + ext.Encoding + NewLine); - AsString(tab, verbose, ext.ExternalContent, buf); - } + if (ext.DirectReference != null) + { + buf.Append(tab + "Direct Reference: " + ext.DirectReference.Id + NewLine); + } + if (ext.IndirectReference != null) + { + buf.Append(tab + "Indirect Reference: " + ext.IndirectReference.ToString() + NewLine); + } + if (ext.DataValueDescriptor != null) + { + AsString(tab, verbose, ext.DataValueDescriptor, buf); + } + buf.Append(tab + "Encoding: " + ext.Encoding + NewLine); + AsString(tab, verbose, ext.ExternalContent, buf); + } else { buf.Append(indent + obj.ToString() + NewLine); @@ -267,7 +262,7 @@ namespace Org.BouncyCastle.Asn1.Utilities buf.Append(indent + type + " ApplicationSpecific[" + app.ApplicationTag + "]" + NewLine); foreach (Asn1Encodable ae in s) { - AsString(indent + Tab, verbose, ae.ToAsn1Object(), buf); + AsString(indent + Tab, verbose, ae.ToAsn1Object(), buf); } } catch (IOException e) @@ -281,98 +276,98 @@ namespace Org.BouncyCastle.Asn1.Utilities + Hex.ToHexString(app.GetContents()) + ")" + NewLine; } - [Obsolete("Use version accepting Asn1Encodable")] - public static string DumpAsString( + [Obsolete("Use version accepting Asn1Encodable")] + public static string DumpAsString( object obj) { if (obj is Asn1Encodable) { - StringBuilder buf = new StringBuilder(); + StringBuilder buf = new StringBuilder(); AsString("", false, ((Asn1Encodable)obj).ToAsn1Object(), buf); - return buf.ToString(); + return buf.ToString(); } return "unknown object type " + obj.ToString(); } - /** - * dump out a DER object as a formatted string, in non-verbose mode - * - * @param obj the Asn1Encodable to be dumped out. - * @return the resulting string. - */ - public static string DumpAsString( - Asn1Encodable obj) - { - return DumpAsString(obj, false); - } + /** + * dump out a DER object as a formatted string, in non-verbose mode + * + * @param obj the Asn1Encodable to be dumped out. + * @return the resulting string. + */ + public static string DumpAsString( + Asn1Encodable obj) + { + return DumpAsString(obj, false); + } - /** - * Dump out the object as a string - * - * @param obj the Asn1Encodable to be dumped out. - * @param verbose if true, dump out the contents of octet and bit strings. - * @return the resulting string. - */ - public static string DumpAsString( - Asn1Encodable obj, - bool verbose) - { - StringBuilder buf = new StringBuilder(); - AsString("", verbose, obj.ToAsn1Object(), buf); - return buf.ToString(); - } + /** + * Dump out the object as a string + * + * @param obj the Asn1Encodable to be dumped out. + * @param verbose if true, dump out the contents of octet and bit strings. + * @return the resulting string. + */ + public static string DumpAsString( + Asn1Encodable obj, + bool verbose) + { + StringBuilder buf = new StringBuilder(); + AsString("", verbose, obj.ToAsn1Object(), buf); + return buf.ToString(); + } - private static string dumpBinaryDataAsString(string indent, byte[] bytes) - { - indent += Tab; + private static string dumpBinaryDataAsString(string indent, byte[] bytes) + { + indent += Tab; - StringBuilder buf = new StringBuilder(NewLine); + StringBuilder buf = new StringBuilder(NewLine); - for (int i = 0; i < bytes.Length; i += SampleSize) - { - if (bytes.Length - i > SampleSize) - { - buf.Append(indent); - buf.Append(Hex.ToHexString(bytes, i, SampleSize)); - buf.Append(Tab); - buf.Append(calculateAscString(bytes, i, SampleSize)); - buf.Append(NewLine); - } - else - { - buf.Append(indent); - buf.Append(Hex.ToHexString(bytes, i, bytes.Length - i)); - for (int j = bytes.Length - i; j != SampleSize; j++) - { - buf.Append(" "); - } - buf.Append(Tab); - buf.Append(calculateAscString(bytes, i, bytes.Length - i)); - buf.Append(NewLine); - } - } + for (int i = 0; i < bytes.Length; i += SampleSize) + { + if (bytes.Length - i > SampleSize) + { + buf.Append(indent); + buf.Append(Hex.ToHexString(bytes, i, SampleSize)); + buf.Append(Tab); + buf.Append(calculateAscString(bytes, i, SampleSize)); + buf.Append(NewLine); + } + else + { + buf.Append(indent); + buf.Append(Hex.ToHexString(bytes, i, bytes.Length - i)); + for (int j = bytes.Length - i; j != SampleSize; j++) + { + buf.Append(" "); + } + buf.Append(Tab); + buf.Append(calculateAscString(bytes, i, bytes.Length - i)); + buf.Append(NewLine); + } + } - return buf.ToString(); - } + return buf.ToString(); + } - private static string calculateAscString( - byte[] bytes, - int off, - int len) - { - StringBuilder buf = new StringBuilder(); + private static string calculateAscString( + byte[] bytes, + int off, + int len) + { + StringBuilder buf = new StringBuilder(); - for (int i = off; i != off + len; i++) - { - char c = (char)bytes[i]; - if (c >= ' ' && c <= '~') - { - buf.Append(c); - } - } + for (int i = off; i != off + len; i++) + { + char c = (char)bytes[i]; + if (c >= ' ' && c <= '~') + { + buf.Append(c); + } + } - return buf.ToString(); - } + return buf.ToString(); + } } } diff --git a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs index 21172f816..7e0695341 100644 --- a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs +++ b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs @@ -41,7 +41,6 @@ namespace Org.BouncyCastle.Asn1.Tests new DerT61String("hello world"), new DerTaggedObject(0, new DerPrintableString("hello world")), new DerUniversalString(data), - new DerUnknownTag(true, 500, data), new DerUtcTime(new DateTime()), new DerUtf8String("hello world"), new DerVisibleString("hello world") -- cgit 1.4.1