From 4206023cd1ba392562ecc3d9b3f37f7e1b456d76 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 8 Jul 2021 17:05:55 +0700 Subject: ASN.1 updates from bc-java --- crypto/src/asn1/Asn1InputStream.cs | 26 +++++++--- crypto/src/asn1/Asn1OctetString.cs | 2 + crypto/src/asn1/BEROctetStringGenerator.cs | 56 +++++++++++----------- crypto/src/asn1/BerOctetString.cs | 36 +++++++++++--- crypto/src/asn1/LazyDERSequence.cs | 10 +--- crypto/src/asn1/LazyDERSet.cs | 8 +--- crypto/src/asn1/crmf/PopoPrivKey.cs | 2 +- .../src/cms/CMSAuthenticatedDataStreamGenerator.cs | 2 +- 8 files changed, 83 insertions(+), 59 deletions(-) diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs index 4f99301b3..d7edae9e0 100644 --- a/crypto/src/asn1/Asn1InputStream.cs +++ b/crypto/src/asn1/Asn1InputStream.cs @@ -133,22 +133,29 @@ namespace Org.BouncyCastle.Asn1 return CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers); } - internal virtual Asn1EncodableVector ReadVector(DefiniteLengthInputStream dIn) + internal virtual Asn1EncodableVector ReadVector() { - if (dIn.Remaining < 1) + Asn1Object o = ReadObject(); + if (null == o) return new Asn1EncodableVector(0); - Asn1InputStream subStream = new Asn1InputStream(dIn); Asn1EncodableVector v = new Asn1EncodableVector(); - Asn1Object o; - while ((o = subStream.ReadObject()) != null) + do { v.Add(o); } - + while ((o = ReadObject()) != null); return v; } + internal virtual Asn1EncodableVector ReadVector(DefiniteLengthInputStream dIn) + { + if (dIn.Remaining < 1) + return new Asn1EncodableVector(0); + + return new Asn1InputStream(dIn).ReadVector(); + } + internal virtual DerSequence CreateDerSequence( DefiniteLengthInputStream dIn) { @@ -405,7 +412,12 @@ namespace Org.BouncyCastle.Asn1 case Asn1Tags.Integer: return new DerInteger(bytes, false); case Asn1Tags.Null: - return DerNull.Instance; // actual content is ignored (enforce 0 length?) + { + if (0 != bytes.Length) + throw new InvalidOperationException("malformed NULL encoding encountered"); + + return DerNull.Instance; + } case Asn1Tags.NumericString: return new DerNumericString(bytes); case Asn1Tags.OctetString: diff --git a/crypto/src/asn1/Asn1OctetString.cs b/crypto/src/asn1/Asn1OctetString.cs index 9a64c7e97..83156e091 100644 --- a/crypto/src/asn1/Asn1OctetString.cs +++ b/crypto/src/asn1/Asn1OctetString.cs @@ -10,6 +10,8 @@ namespace Org.BouncyCastle.Asn1 public abstract class Asn1OctetString : Asn1Object, Asn1OctetStringParser { + internal static readonly byte[] EmptyOctets = new byte[0]; + internal byte[] str; /** diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs index f34538f38..0bef886f2 100644 --- a/crypto/src/asn1/BEROctetStringGenerator.cs +++ b/crypto/src/asn1/BEROctetStringGenerator.cs @@ -72,35 +72,35 @@ namespace Org.BouncyCastle.Asn1 } } - public override void Write( - byte[] buf, - int offset, - int len) + public override void Write(byte[] b, int off, int len) { - while (len > 0) - { - int numToCopy = System.Math.Min(len, _buf.Length - _off); - - if (numToCopy == _buf.Length) - { - DerOctetString.Encode(_derOut, buf, offset, numToCopy); - } - else - { - Array.Copy(buf, offset, _buf, _off, numToCopy); - - _off += numToCopy; - if (_off < _buf.Length) - break; - - DerOctetString.Encode(_derOut, _buf, 0, _off); - _off = 0; - } - - offset += numToCopy; - len -= numToCopy; - } - } + int bufLen = _buf.Length; + int available = bufLen - _off; + if (len < available) + { + Array.Copy(b, off, _buf, _off, len); + _off += len; + return; + } + + int count = 0; + if (_off > 0) + { + Array.Copy(b, off, _buf, _off, available); + count += available; + DerOctetString.Encode(_derOut, _buf, 0, bufLen); + } + + int remaining; + while ((remaining = len - count) >= bufLen) + { + DerOctetString.Encode(_derOut, b, off + count, bufLen); + count += bufLen; + } + + Array.Copy(b, off + count, _buf, 0, remaining); + this._off = remaining; + } #if PORTABLE protected override void Dispose(bool disposing) diff --git a/crypto/src/asn1/BerOctetString.cs b/crypto/src/asn1/BerOctetString.cs index f41aaf6a5..2b4de4b2f 100644 --- a/crypto/src/asn1/BerOctetString.cs +++ b/crypto/src/asn1/BerOctetString.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Diagnostics; using System.IO; using Org.BouncyCastle.Utilities; @@ -22,15 +23,36 @@ namespace Org.BouncyCastle.Asn1 return new BerOctetString(v); } - private static byte[] ToBytes(Asn1OctetString[] octs) + internal static byte[] FlattenOctetStrings(Asn1OctetString[] octetStrings) { - MemoryStream bOut = new MemoryStream(); - foreach (Asn1OctetString o in octs) + int count = octetStrings.Length; + switch (count) { - byte[] octets = o.GetOctets(); - bOut.Write(octets, 0, octets.Length); + case 0: + return EmptyOctets; + case 1: + return octetStrings[0].str; + default: + { + int totalOctets = 0; + for (int i = 0; i < count; ++i) + { + totalOctets += octetStrings[i].str.Length; + } + + byte[] str = new byte[totalOctets]; + int pos = 0; + for (int i = 0; i < count; ++i) + { + byte[] octets = octetStrings[i].str; + Array.Copy(octets, 0, str, pos, octets.Length); + pos += octets.Length; + } + + Debug.Assert(pos == totalOctets); + return str; + } } - return bOut.ToArray(); } private static Asn1OctetString[] ToOctetStringArray(IEnumerable e) @@ -71,7 +93,7 @@ namespace Org.BouncyCastle.Asn1 } public BerOctetString(Asn1OctetString[] octs, int chunkSize) - : this(ToBytes(octs), octs, chunkSize) + : this(FlattenOctetStrings(octs), octs, chunkSize) { } diff --git a/crypto/src/asn1/LazyDERSequence.cs b/crypto/src/asn1/LazyDERSequence.cs index 8fa7a0792..78e9df151 100644 --- a/crypto/src/asn1/LazyDERSequence.cs +++ b/crypto/src/asn1/LazyDERSequence.cs @@ -21,19 +21,13 @@ namespace Org.BouncyCastle.Asn1 { if (null != encoded) { - Asn1EncodableVector v = new Asn1EncodableVector(); Asn1InputStream e = new LazyAsn1InputStream(encoded); - - Asn1Object o; - while ((o = e.ReadObject()) != null) - { - v.Add(o); - } + Asn1EncodableVector v = e.ReadVector(); this.elements = v.TakeElements(); this.encoded = null; } - } + } } public override Asn1Encodable this[int index] diff --git a/crypto/src/asn1/LazyDERSet.cs b/crypto/src/asn1/LazyDERSet.cs index eac64cbbe..25dbdd0a4 100644 --- a/crypto/src/asn1/LazyDERSet.cs +++ b/crypto/src/asn1/LazyDERSet.cs @@ -21,14 +21,8 @@ namespace Org.BouncyCastle.Asn1 { if (encoded != null) { - Asn1EncodableVector v = new Asn1EncodableVector(); Asn1InputStream e = new LazyAsn1InputStream(encoded); - - Asn1Object o; - while ((o = e.ReadObject()) != null) - { - v.Add(o); - } + Asn1EncodableVector v = e.ReadVector(); this.elements = v.TakeElements(); this.encoded = null; diff --git a/crypto/src/asn1/crmf/PopoPrivKey.cs b/crypto/src/asn1/crmf/PopoPrivKey.cs index 2b38cb109..95a4484de 100644 --- a/crypto/src/asn1/crmf/PopoPrivKey.cs +++ b/crypto/src/asn1/crmf/PopoPrivKey.cs @@ -44,7 +44,7 @@ namespace Org.BouncyCastle.Asn1.Crmf public static PopoPrivKey GetInstance(Asn1TaggedObject tagged, bool isExplicit) { - return new PopoPrivKey(Asn1TaggedObject.GetInstance(tagged.GetObject())); + return new PopoPrivKey(Asn1TaggedObject.GetInstance(tagged, true)); } public PopoPrivKey(SubsequentMessage msg) diff --git a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs index 9d9e2450c..b77758d1f 100644 --- a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs +++ b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs @@ -163,7 +163,7 @@ namespace Org.BouncyCastle.Cms eiGen.AddObject(CmsObjectIdentifiers.Data); Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream( - eiGen.GetRawOutputStream(), 0, false, _bufferSize); + eiGen.GetRawOutputStream(), 0, true, _bufferSize); IMac mac = MacUtilities.GetMac(macAlgId.Algorithm); // TODO Confirm no ParametersWithRandom needed -- cgit 1.4.1