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
|