diff --git a/crypto/src/asn1/ASN1StreamParser.cs b/crypto/src/asn1/ASN1StreamParser.cs
index 3eaaadaee..860dc99b1 100644
--- a/crypto/src/asn1/ASN1StreamParser.cs
+++ b/crypto/src/asn1/ASN1StreamParser.cs
@@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Asn1
if (_in is IndefiniteLengthInputStream)
{
if (!constructed)
- throw new IOException("indefinite length primitive encoding encountered");
+ throw new IOException("indefinite-length primitive encoding encountered");
return ReadIndef(tag);
}
@@ -134,12 +134,13 @@ namespace Org.BouncyCastle.Asn1
//
// calculate length
//
- int length = Asn1InputStream.ReadLength(_in, _limit);
+ int length = Asn1InputStream.ReadLength(_in, _limit,
+ tagNo == Asn1Tags.OctetString || tagNo == Asn1Tags.Sequence || tagNo == Asn1Tags.Set || tagNo == Asn1Tags.External);
- if (length < 0) // indefinite length method
+ if (length < 0) // indefinite-length method
{
if (!isConstructed)
- throw new IOException("indefinite length primitive encoding encountered");
+ throw new IOException("indefinite-length primitive encoding encountered");
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
Asn1StreamParser sp = new Asn1StreamParser(indIn, _limit);
@@ -158,7 +159,7 @@ namespace Org.BouncyCastle.Asn1
}
else
{
- DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length, _limit);
if ((tag & Asn1Tags.Application) != 0)
{
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 0c7461c98..4f99301b3 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -2,6 +2,7 @@ using System;
using System.Diagnostics;
using System.IO;
+using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
@@ -22,10 +23,12 @@ namespace Org.BouncyCastle.Asn1
internal static int FindLimit(Stream input)
{
if (input is LimitedInputStream)
- {
- return ((LimitedInputStream)input).GetRemaining();
- }
- else if (input is MemoryStream)
+ return ((LimitedInputStream)input).Limit;
+
+ if (input is Asn1InputStream)
+ return ((Asn1InputStream)input).Limit;
+
+ if (input is MemoryStream)
{
MemoryStream mem = (MemoryStream)input;
return (int)(mem.Length - mem.Position);
@@ -77,7 +80,7 @@ namespace Org.BouncyCastle.Asn1
{
bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
- DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length);
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length, limit);
if ((tag & Asn1Tags.Application) != 0)
{
@@ -95,10 +98,27 @@ namespace Org.BouncyCastle.Asn1
switch (tagNo)
{
case Asn1Tags.OctetString:
+ {
//
// yes, people actually do this...
//
- return new BerOctetString(ReadVector(defIn));
+ Asn1EncodableVector v = ReadVector(defIn);
+ Asn1OctetString[] strings = new Asn1OctetString[v.Count];
+
+ for (int i = 0; i != strings.Length; i++)
+ {
+ Asn1Encodable asn1Obj = v[i];
+ if (!(asn1Obj is Asn1OctetString))
+ {
+ throw new Asn1Exception("unknown object encountered in constructed OCTET STRING: "
+ + Platform.GetTypeName(asn1Obj));
+ }
+
+ strings[i] = (Asn1OctetString)asn1Obj;
+ }
+
+ return new BerOctetString(strings);
+ }
case Asn1Tags.Sequence:
return CreateDerSequence(defIn);
case Asn1Tags.Set:
@@ -162,12 +182,12 @@ namespace Org.BouncyCastle.Asn1
//
// calculate length
//
- int length = ReadLength(this.s, limit);
+ int length = ReadLength(this.s, limit, false);
- if (length < 0) // indefinite length method
+ if (length < 0) // indefinite-length method
{
if (!isConstructed)
- throw new IOException("indefinite length primitive encoding encountered");
+ throw new IOException("indefinite-length primitive encoding encountered");
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit);
Asn1StreamParser sp = new Asn1StreamParser(indIn, limit);
@@ -210,6 +230,11 @@ namespace Org.BouncyCastle.Asn1
}
}
+ internal virtual int Limit
+ {
+ get { return limit; }
+ }
+
internal static int ReadTagNumber(
Stream s,
int tag)
@@ -228,9 +253,7 @@ namespace Org.BouncyCastle.Asn1
// 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");
- }
+ throw new IOException("corrupted stream - invalid high tag number found");
while ((b >= 0) && ((b & 0x80) != 0))
{
@@ -248,9 +271,7 @@ namespace Org.BouncyCastle.Asn1
return tagNo;
}
- internal static int ReadLength(
- Stream s,
- int limit)
+ internal static int ReadLength(Stream s, int limit, bool isParsing)
{
int length = s.ReadByte();
if (length < 0)
@@ -279,18 +300,18 @@ namespace Org.BouncyCastle.Asn1
}
if (length < 0)
- throw new IOException("Corrupted stream - negative length found");
+ 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");
+ if (length >= limit && !isParsing) // after all we must have read at least 1 byte
+ throw new IOException("corrupted stream - out of bounds length found: " + length + " >= " + limit);
}
return length;
}
- internal static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
+ private static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
{
- int len = defIn.GetRemaining();
+ int len = defIn.Remaining;
if (len >= tmpBuffers.Length)
{
return defIn.ToArray();
@@ -307,6 +328,49 @@ namespace Org.BouncyCastle.Asn1
return buf;
}
+ private static char[] GetBmpCharBuffer(DefiniteLengthInputStream defIn)
+ {
+ int remainingBytes = defIn.Remaining;
+ if (0 != (remainingBytes & 1))
+ throw new IOException("malformed BMPString encoding encountered");
+
+ char[] str = new char[remainingBytes / 2];
+ int stringPos = 0;
+
+ byte[] buf = new byte[8];
+ while (remainingBytes >= 8)
+ {
+ if (Streams.ReadFully(defIn, buf, 0, 8) != 8)
+ throw new EndOfStreamException("EOF encountered in middle of BMPString");
+
+ str[stringPos ] = (char)((buf[0] << 8) | (buf[1] & 0xFF));
+ str[stringPos + 1] = (char)((buf[2] << 8) | (buf[3] & 0xFF));
+ str[stringPos + 2] = (char)((buf[4] << 8) | (buf[5] & 0xFF));
+ str[stringPos + 3] = (char)((buf[6] << 8) | (buf[7] & 0xFF));
+ stringPos += 4;
+ remainingBytes -= 8;
+ }
+ if (remainingBytes > 0)
+ {
+ if (Streams.ReadFully(defIn, buf, 0, remainingBytes) != remainingBytes)
+ throw new EndOfStreamException("EOF encountered in middle of BMPString");
+
+ int bufPos = 0;
+ do
+ {
+ int b1 = buf[bufPos++] << 8;
+ int b2 = buf[bufPos++] & 0xFF;
+ str[stringPos++] = (char)(b1 | b2);
+ }
+ while (bufPos < remainingBytes);
+ }
+
+ if (0 != defIn.Remaining || str.Length != stringPos)
+ throw new InvalidOperationException();
+
+ return str;
+ }
+
internal static Asn1Object CreatePrimitiveDerObject(
int tagNo,
DefiniteLengthInputStream defIn,
@@ -314,6 +378,8 @@ namespace Org.BouncyCastle.Asn1
{
switch (tagNo)
{
+ case Asn1Tags.BmpString:
+ return new DerBmpString(GetBmpCharBuffer(defIn));
case Asn1Tags.Boolean:
return DerBoolean.FromOctetString(GetBuffer(defIn, tmpBuffers));
case Asn1Tags.Enumerated:
@@ -328,8 +394,6 @@ namespace Org.BouncyCastle.Asn1
{
case Asn1Tags.BitString:
return DerBitString.FromAsn1Octets(bytes);
- case Asn1Tags.BmpString:
- return new DerBmpString(bytes);
case Asn1Tags.GeneralizedTime:
return new DerGeneralizedTime(bytes);
case Asn1Tags.GeneralString:
@@ -339,7 +403,7 @@ namespace Org.BouncyCastle.Asn1
case Asn1Tags.IA5String:
return new DerIA5String(bytes);
case Asn1Tags.Integer:
- return new DerInteger(bytes);
+ return new DerInteger(bytes, false);
case Asn1Tags.Null:
return DerNull.Instance; // actual content is ignored (enforce 0 length?)
case Asn1Tags.NumericString:
diff --git a/crypto/src/asn1/Asn1OctetString.cs b/crypto/src/asn1/Asn1OctetString.cs
index 73b6e51bf..da7dfae46 100644
--- a/crypto/src/asn1/Asn1OctetString.cs
+++ b/crypto/src/asn1/Asn1OctetString.cs
@@ -67,20 +67,7 @@ namespace Org.BouncyCastle.Asn1
this.str = str;
}
- internal Asn1OctetString(
- Asn1Encodable obj)
- {
- try
- {
- this.str = obj.GetEncoded(Asn1Encodable.Der);
- }
- catch (IOException e)
- {
- throw new ArgumentException("Error processing object : " + e.ToString());
- }
- }
-
- public Stream GetOctetStream()
+ public Stream GetOctetStream()
{
return new MemoryStream(str, false);
}
diff --git a/crypto/src/asn1/BerOctetString.cs b/crypto/src/asn1/BerOctetString.cs
index a7c8ad33e..fb4291612 100644
--- a/crypto/src/asn1/BerOctetString.cs
+++ b/crypto/src/asn1/BerOctetString.cs
@@ -9,66 +9,77 @@ namespace Org.BouncyCastle.Asn1
public class BerOctetString
: DerOctetString, IEnumerable
{
- public static BerOctetString FromSequence(Asn1Sequence seq)
- {
- IList v = Platform.CreateArrayList();
-
- foreach (Asn1Encodable obj in seq)
- {
- v.Add(obj);
- }
-
- return new BerOctetString(v);
- }
+ private static readonly int DefaultChunkSize = 1000;
- private const int MaxLength = 1000;
+ public static BerOctetString FromSequence(Asn1Sequence seq)
+ {
+ int count = seq.Count;
+ Asn1OctetString[] v = new Asn1OctetString[count];
+ for (int i = 0; i < count; ++i)
+ {
+ v[i] = Asn1OctetString.GetInstance(seq[i]);
+ }
+ return new BerOctetString(v);
+ }
- /**
- * convert a vector of octet strings into a single byte string
- */
- private static byte[] ToBytes(
- IEnumerable octs)
+ private static byte[] ToBytes(Asn1OctetString[] octs)
{
MemoryStream bOut = new MemoryStream();
- foreach (DerOctetString o in octs)
- {
+ foreach (Asn1OctetString o in octs)
+ {
byte[] octets = o.GetOctets();
bOut.Write(octets, 0, octets.Length);
}
- return bOut.ToArray();
+ return bOut.ToArray();
+ }
+
+ private static Asn1OctetString[] ToOctetStringArray(IEnumerable e)
+ {
+ IList list = Platform.CreateArrayList(e);
+
+ int count = list.Count;
+ Asn1OctetString[] v = new Asn1OctetString[count];
+ for (int i = 0; i < count; ++i)
+ {
+ v[i] = Asn1OctetString.GetInstance(list[i]);
+ }
+ return v;
}
- private readonly IEnumerable octs;
+ private readonly int chunkSize;
+ private readonly Asn1OctetString[] octs;
+
+ [Obsolete("Will be removed")]
+ public BerOctetString(IEnumerable e)
+ : this(ToOctetStringArray(e))
+ {
+ }
- /// <param name="str">The octets making up the octet string.</param>
- public BerOctetString(
- byte[] str)
- : base(str)
+ public BerOctetString(byte[] str)
+ : this(str, DefaultChunkSize)
{
}
- public BerOctetString(
- IEnumerable octets)
- : base(ToBytes(octets))
+ public BerOctetString(Asn1OctetString[] octs)
+ : this(octs, DefaultChunkSize)
{
- this.octs = octets;
}
- public BerOctetString(
- Asn1Object obj)
- : base(obj)
+ public BerOctetString(byte[] str, int chunkSize)
+ : this(str, null, chunkSize)
{
}
- public BerOctetString(
- Asn1Encodable obj)
- : base(obj.ToAsn1Object())
+ public BerOctetString(Asn1OctetString[] octs, int chunkSize)
+ : this(ToBytes(octs), octs, chunkSize)
{
}
- public override byte[] GetOctets()
+ private BerOctetString(byte[] str, Asn1OctetString[] octs, int chunkSize)
+ : base(str)
{
- return str;
+ this.octs = octs;
+ this.chunkSize = chunkSize;
}
/**
@@ -93,17 +104,17 @@ namespace Org.BouncyCastle.Asn1
private IList GenerateOcts()
{
IList vec = Platform.CreateArrayList();
- for (int i = 0; i < str.Length; i += MaxLength)
- {
- int end = System.Math.Min(str.Length, i + MaxLength);
+ for (int i = 0; i < str.Length; i += chunkSize)
+ {
+ int end = System.Math.Min(str.Length, i + chunkSize);
- byte[] nStr = new byte[end - i];
+ byte[] nStr = new byte[end - i];
- Array.Copy(str, i, nStr, 0, nStr.Length);
+ Array.Copy(str, i, nStr, 0, nStr.Length);
- vec.Add(new DerOctetString(nStr));
- }
- return vec;
+ vec.Add(new DerOctetString(nStr));
+ }
+ return vec;
}
internal override void Encode(
@@ -118,7 +129,7 @@ namespace Org.BouncyCastle.Asn1
//
// write out the octet array
//
- foreach (DerOctetString oct in this)
+ foreach (Asn1OctetString oct in this)
{
derOut.WriteObject(oct);
}
diff --git a/crypto/src/asn1/ConstructedOctetStream.cs b/crypto/src/asn1/ConstructedOctetStream.cs
index 1773b22cc..829a9a427 100644
--- a/crypto/src/asn1/ConstructedOctetStream.cs
+++ b/crypto/src/asn1/ConstructedOctetStream.cs
@@ -1,5 +1,6 @@
using System.IO;
+using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
@@ -25,13 +26,12 @@ namespace Org.BouncyCastle.Asn1
if (!_first)
return 0;
- Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject();
-
- if (s == null)
- return 0;
+ Asn1OctetStringParser next = GetNextParser();
+ if (next == null)
+ return 0;
_first = false;
- _currentStream = s.GetOctetStream();
+ _currentStream = next.GetOctetStream();
}
int totalRead = 0;
@@ -49,15 +49,14 @@ namespace Org.BouncyCastle.Asn1
}
else
{
- Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject();
-
- if (aos == null)
+ Asn1OctetStringParser next = GetNextParser();
+ if (next == null)
{
_currentStream = null;
return totalRead;
}
- _currentStream = aos.GetOctetStream();
+ _currentStream = next.GetOctetStream();
}
}
}
@@ -69,13 +68,12 @@ namespace Org.BouncyCastle.Asn1
if (!_first)
return 0;
- Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject();
-
- if (s == null)
+ Asn1OctetStringParser next = GetNextParser();
+ if (next == null)
return 0;
_first = false;
- _currentStream = s.GetOctetStream();
+ _currentStream = next.GetOctetStream();
}
for (;;)
@@ -83,20 +81,29 @@ namespace Org.BouncyCastle.Asn1
int b = _currentStream.ReadByte();
if (b >= 0)
- {
return b;
- }
-
- Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject();
- if (aos == null)
+ Asn1OctetStringParser next = GetNextParser();
+ if (next == null)
{
_currentStream = null;
return -1;
}
- _currentStream = aos.GetOctetStream();
+ _currentStream = next.GetOctetStream();
}
}
+
+ private Asn1OctetStringParser GetNextParser()
+ {
+ IAsn1Convertible asn1Obj = _parser.ReadObject();
+ if (asn1Obj == null)
+ return null;
+
+ if (asn1Obj is Asn1OctetStringParser)
+ return (Asn1OctetStringParser)asn1Obj;
+
+ throw new IOException("unknown object encountered: " + Platform.GetTypeName(asn1Obj));
+ }
}
}
diff --git a/crypto/src/asn1/DefiniteLengthInputStream.cs b/crypto/src/asn1/DefiniteLengthInputStream.cs
index 4ae803c0e..d10ea4d12 100644
--- a/crypto/src/asn1/DefiniteLengthInputStream.cs
+++ b/crypto/src/asn1/DefiniteLengthInputStream.cs
@@ -13,10 +13,8 @@ namespace Org.BouncyCastle.Asn1
private readonly int _originalLength;
private int _remaining;
- internal DefiniteLengthInputStream(
- Stream inStream,
- int length)
- : base(inStream, length)
+ internal DefiniteLengthInputStream(Stream inStream, int length, int limit)
+ : base(inStream, limit)
{
if (length < 0)
throw new ArgumentException("negative lengths not allowed", "length");
@@ -30,7 +28,7 @@ namespace Org.BouncyCastle.Asn1
}
}
- internal int Remaining
+ internal int Remaining
{
get { return _remaining; }
}
@@ -80,6 +78,14 @@ namespace Org.BouncyCastle.Asn1
if (_remaining != buf.Length)
throw new ArgumentException("buffer length not right for data");
+ if (_remaining == 0)
+ return;
+
+ // make sure it's safe to do this!
+ int limit = Limit;
+ if (_remaining >= limit)
+ throw new IOException("corrupted stream - out of bounds length found: " + _remaining + " >= " + limit);
+
if ((_remaining -= Streams.ReadFully(_in, buf)) != 0)
throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
SetParentEofDetect(true);
@@ -90,7 +96,12 @@ namespace Org.BouncyCastle.Asn1
if (_remaining == 0)
return EmptyBytes;
- byte[] bytes = new byte[_remaining];
+ // make sure it's safe to do this!
+ int limit = Limit;
+ if (_remaining >= limit)
+ throw new IOException("corrupted stream - out of bounds length found: " + _remaining + " >= " + limit);
+
+ byte[] bytes = new byte[_remaining];
if ((_remaining -= Streams.ReadFully(_in, bytes)) != 0)
throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
SetParentEofDetect(true);
diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs
index 33d950ff8..061900b9c 100644
--- a/crypto/src/asn1/DerBMPString.cs
+++ b/crypto/src/asn1/DerBMPString.cs
@@ -55,32 +55,44 @@ namespace Org.BouncyCastle.Asn1
/**
* basic constructor - byte encoded string.
*/
- public DerBmpString(
- byte[] str)
+ [Obsolete("Will become internal")]
+ public DerBmpString(byte[] str)
{
if (str == null)
throw new ArgumentNullException("str");
- char[] cs = new char[str.Length / 2];
+ int byteLen = str.Length;
+ if (0 != (byteLen & 1))
+ throw new ArgumentException("malformed BMPString encoding encountered", "str");
- for (int i = 0; i != cs.Length; i++)
+ int charLen = byteLen / 2;
+ char[] cs = new char[charLen];
+
+ for (int i = 0; i != charLen; i++)
{
cs[i] = (char)((str[2 * i] << 8) | (str[2 * i + 1] & 0xff));
}
- this.str = new string(cs);
+ this.str = new string(cs);
+ }
+
+ internal DerBmpString(char[] str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ this.str = new string(str);
}
/**
* basic constructor
*/
- public DerBmpString(
- string str)
+ public DerBmpString(string str)
{
if (str == null)
throw new ArgumentNullException("str");
- this.str = str;
+ this.str = str;
}
public override string GetString()
diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs
index 3e19a07b6..4f7b68d35 100644
--- a/crypto/src/asn1/DerInteger.cs
+++ b/crypto/src/asn1/DerInteger.cs
@@ -145,6 +145,18 @@ namespace Org.BouncyCastle.Asn1
}
}
+ public long LongValueExact
+ {
+ get
+ {
+ int count = bytes.Length - start;
+ if (count > 8)
+ throw new ArithmeticException("ASN.1 Integer out of long range");
+
+ return LongValue(bytes, start, SignExtSigned);
+ }
+ }
+
internal override void Encode(DerOutputStream derOut)
{
derOut.WriteEncoded(Asn1Tags.Integer, bytes);
@@ -182,6 +194,19 @@ namespace Org.BouncyCastle.Asn1
return val;
}
+ internal static long LongValue(byte[] bytes, int start, int signExt)
+ {
+ int length = bytes.Length;
+ int pos = System.Math.Max(start, length - 8);
+
+ long val = (sbyte)bytes[pos] & signExt;
+ while (++pos < length)
+ {
+ val = (val << 8) | bytes[pos];
+ }
+ return val;
+ }
+
/**
* Apply the correct validation for an INTEGER primitive following the BER rules.
*
diff --git a/crypto/src/asn1/DerOctetString.cs b/crypto/src/asn1/DerOctetString.cs
index c046c9402..d79607950 100644
--- a/crypto/src/asn1/DerOctetString.cs
+++ b/crypto/src/asn1/DerOctetString.cs
@@ -1,3 +1,5 @@
+using System;
+
namespace Org.BouncyCastle.Asn1
{
public class DerOctetString
@@ -10,9 +12,13 @@ namespace Org.BouncyCastle.Asn1
{
}
- public DerOctetString(
- Asn1Encodable obj)
- : base(obj)
+ public DerOctetString(IAsn1Convertible obj)
+ : this(obj.ToAsn1Object())
+ {
+ }
+
+ public DerOctetString(Asn1Encodable obj)
+ : base(obj.GetEncoded(Asn1Encodable.Der))
{
}
diff --git a/crypto/src/asn1/LimitedInputStream.cs b/crypto/src/asn1/LimitedInputStream.cs
index 62486aa77..98a45876d 100644
--- a/crypto/src/asn1/LimitedInputStream.cs
+++ b/crypto/src/asn1/LimitedInputStream.cs
@@ -8,23 +8,20 @@ namespace Org.BouncyCastle.Asn1
: BaseInputStream
{
protected readonly Stream _in;
- private int _limit;
+ private int _limit;
- internal LimitedInputStream(
- Stream inStream,
- int limit)
+ internal LimitedInputStream(Stream inStream, int limit)
{
this._in = inStream;
- this._limit = limit;
+ this._limit = limit;
}
- internal virtual int GetRemaining()
- {
- // TODO: maybe one day this can become more accurate
- return _limit;
- }
+ internal virtual int Limit
+ {
+ get { return _limit; }
+ }
- protected virtual void SetParentEofDetect(bool on)
+ protected virtual void SetParentEofDetect(bool on)
{
if (_in is IndefiniteLengthInputStream)
{
diff --git a/crypto/src/asn1/cms/SignedData.cs b/crypto/src/asn1/cms/SignedData.cs
index dfc1e2829..5eba8390d 100644
--- a/crypto/src/asn1/cms/SignedData.cs
+++ b/crypto/src/asn1/cms/SignedData.cs
@@ -25,16 +25,13 @@ namespace Org.BouncyCastle.Asn1.Cms
private readonly bool certsBer;
private readonly bool crlsBer;
- public static SignedData GetInstance(
- object obj)
+ public static SignedData GetInstance(object obj)
{
if (obj is SignedData)
- return (SignedData) obj;
-
- if (obj is Asn1Sequence)
- return new SignedData((Asn1Sequence) obj);
-
- throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
+ return (SignedData)obj;
+ if (obj == null)
+ return null;
+ return new SignedData(Asn1Sequence.GetInstance(obj));
}
public SignedData(
|