summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/src/asn1/Asn1InputStream.cs26
-rw-r--r--crypto/src/asn1/Asn1OctetString.cs2
-rw-r--r--crypto/src/asn1/BEROctetStringGenerator.cs56
-rw-r--r--crypto/src/asn1/BerOctetString.cs36
-rw-r--r--crypto/src/asn1/LazyDERSequence.cs10
-rw-r--r--crypto/src/asn1/LazyDERSet.cs8
-rw-r--r--crypto/src/asn1/crmf/PopoPrivKey.cs2
-rw-r--r--crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs2
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