diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-10-15 14:18:36 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-10-15 14:18:36 +0700 |
commit | e3acb177d13bfe158aca5aff2b5a9d8cef269d5d (patch) | |
tree | 27dc72e89c7c29857f4787b9a328b1d06b331b2c /crypto/src | |
parent | ASN1InputStream updates from bc-java (diff) | |
download | BouncyCastle.NET-ed25519-e3acb177d13bfe158aca5aff2b5a9d8cef269d5d.tar.xz |
Improve ASN.1 substream handling
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/asn1/ASN1StreamParser.cs | 112 | ||||
-rw-r--r-- | crypto/src/asn1/Asn1InputStream.cs | 48 |
2 files changed, 83 insertions, 77 deletions
diff --git a/crypto/src/asn1/ASN1StreamParser.cs b/crypto/src/asn1/ASN1StreamParser.cs index 860dc99b1..cca333412 100644 --- a/crypto/src/asn1/ASN1StreamParser.cs +++ b/crypto/src/asn1/ASN1StreamParser.cs @@ -10,31 +10,32 @@ namespace Org.BouncyCastle.Asn1 private readonly byte[][] tmpBuffers; - public Asn1StreamParser( - Stream inStream) - : this(inStream, Asn1InputStream.FindLimit(inStream)) + public Asn1StreamParser(Stream input) + : this(input, Asn1InputStream.FindLimit(input)) { } - public Asn1StreamParser( - Stream inStream, - int limit) - { - if (!inStream.CanRead) - throw new ArgumentException("Expected stream to be readable", "inStream"); - - this._in = inStream; - this._limit = limit; - this.tmpBuffers = new byte[16][]; + public Asn1StreamParser(byte[] encoding) + : this(new MemoryStream(encoding, false), encoding.Length) + { } - public Asn1StreamParser( - byte[] encoding) - : this(new MemoryStream(encoding, false), encoding.Length) + public Asn1StreamParser(Stream input, int limit) + : this(input, limit, new byte[16][]) { - } + } + + internal Asn1StreamParser(Stream input, int limit, byte[][] tmpBuffers) + { + if (!input.CanRead) + throw new ArgumentException("Expected stream to be readable", "input"); + + this._in = input; + this._limit = limit; + this.tmpBuffers = tmpBuffers; + } - internal IAsn1Convertible ReadIndef(int tagValue) + internal IAsn1Convertible ReadIndef(int tagValue) { // Note: INDEF => CONSTRUCTED @@ -142,10 +143,10 @@ namespace Org.BouncyCastle.Asn1 if (!isConstructed) throw new IOException("indefinite-length primitive encoding encountered"); - IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit); - Asn1StreamParser sp = new Asn1StreamParser(indIn, _limit); + IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit); + Asn1StreamParser sp = new Asn1StreamParser(indIn, _limit, tmpBuffers); - if ((tag & Asn1Tags.Application) != 0) + if ((tag & Asn1Tags.Application) != 0) { return new BerApplicationSpecificParser(tagNo, sp); } @@ -168,45 +169,48 @@ namespace Org.BouncyCastle.Asn1 if ((tag & Asn1Tags.Tagged) != 0) { - return new BerTaggedObjectParser(isConstructed, tagNo, new Asn1StreamParser(defIn)); + return new BerTaggedObjectParser(isConstructed, tagNo, + new Asn1StreamParser(defIn, defIn.Remaining, tmpBuffers)); } - 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 BerOctetStringParser(new Asn1StreamParser(defIn)); - case Asn1Tags.Sequence: - return new DerSequenceParser(new Asn1StreamParser(defIn)); - case Asn1Tags.Set: - return new DerSetParser(new Asn1StreamParser(defIn)); - case Asn1Tags.External: - return new DerExternalParser(new Asn1StreamParser(defIn)); - default: - throw new IOException("unknown tag " + tagNo + " encountered"); + if (!isConstructed) + { + // Some primitive encodings can be handled by parsers too... + switch (tagNo) + { + case Asn1Tags.OctetString: + return new DerOctetStringParser(defIn); } - } - // Some primitive encodings can be handled by parsers too... - switch (tagNo) - { - case Asn1Tags.OctetString: - return new DerOctetStringParser(defIn); - } + try + { + return Asn1InputStream.CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers); + } + catch (ArgumentException e) + { + throw new Asn1Exception("corrupted stream detected", e); + } + } - try - { - return Asn1InputStream.CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers); - } - catch (ArgumentException e) + Asn1StreamParser sp = new Asn1StreamParser(defIn, defIn.Remaining, tmpBuffers); + + // TODO There are other tags that may be constructed (e.g. BitString) + switch (tagNo) { - throw new Asn1Exception("corrupted stream detected", e); - } + case Asn1Tags.OctetString: + // + // yes, people actually do this... + // + return new BerOctetStringParser(sp); + case Asn1Tags.Sequence: + return new DerSequenceParser(sp); + case Asn1Tags.Set: + return new DerSetParser(sp); + case Asn1Tags.External: + return new DerExternalParser(sp); + default: + throw new IOException("unknown tag " + tagNo + " encountered"); + } } } diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs index 6bb6311e1..ff3590122 100644 --- a/crypto/src/asn1/Asn1InputStream.cs +++ b/crypto/src/asn1/Asn1InputStream.cs @@ -37,39 +37,40 @@ namespace Org.BouncyCastle.Asn1 return int.MaxValue; } - public Asn1InputStream( - Stream inputStream) - : this(inputStream, FindLimit(inputStream)) + public Asn1InputStream(Stream input) + : this(input, FindLimit(input)) { } /** - * Create an ASN1InputStream where no DER object will be longer than limit. + * 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 stream containing ASN.1 encoded data. - * @param limit maximum size of a DER encoded object. + * @param input array containing ASN.1 encoded data. */ - public Asn1InputStream( - Stream inputStream, - int limit) - : base(inputStream) + public Asn1InputStream(byte[] input) + : this(new MemoryStream(input, false), input.Length) { - 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. + * Create an ASN1InputStream where no DER object will be longer than limit. * - * @param input array containing ASN.1 encoded data. + * @param input stream containing ASN.1 encoded data. + * @param limit maximum size of a DER encoded object. */ - public Asn1InputStream( - byte[] input) - : this(new MemoryStream(input, false), input.Length) + public Asn1InputStream(Stream input, int limit) + : this(input, limit, new byte[16][]) { } + private Asn1InputStream(Stream input, int limit, byte[][] tmpBuffers) + : base(input) + { + this.limit = limit; + this.tmpBuffers = tmpBuffers; + } + /** * build an object given its tag and the number of bytes to construct it from. */ @@ -89,7 +90,7 @@ namespace Org.BouncyCastle.Asn1 if ((tag & Asn1Tags.Tagged) != 0) { - return new Asn1StreamParser(defIn).ReadTaggedObject(isConstructed, tagNo); + return new Asn1StreamParser(defIn, defIn.Remaining, tmpBuffers).ReadTaggedObject(isConstructed, tagNo); } if (isConstructed) @@ -148,12 +149,13 @@ namespace Org.BouncyCastle.Asn1 return v; } - internal virtual Asn1EncodableVector ReadVector(DefiniteLengthInputStream dIn) + internal virtual Asn1EncodableVector ReadVector(DefiniteLengthInputStream defIn) { - if (dIn.Remaining < 1) + int remaining = defIn.Remaining; + if (remaining < 1) return new Asn1EncodableVector(0); - return new Asn1InputStream(dIn).ReadVector(); + return new Asn1InputStream(defIn, remaining, tmpBuffers).ReadVector(); } internal virtual DerSequence CreateDerSequence( @@ -197,7 +199,7 @@ namespace Org.BouncyCastle.Asn1 throw new IOException("indefinite-length primitive encoding encountered"); IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit); - Asn1StreamParser sp = new Asn1StreamParser(indIn, limit); + Asn1StreamParser sp = new Asn1StreamParser(indIn, limit, tmpBuffers); if ((tag & Asn1Tags.Application) != 0) { |