diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2019-08-01 15:20:29 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2019-08-01 15:20:29 +0700 |
commit | abe0572ea59671d9444b61bf3ad4458518c2805d (patch) | |
tree | ec5fcb0c70214b941c036589be9656ca79d24a3b | |
parent | Rework some of the ImplSquare methods in custom binary curves (diff) | |
download | BouncyCastle.NET-ed25519-abe0572ea59671d9444b61bf3ad4458518c2805d.tar.xz |
Misc. ASN.1 updates from bc-java
-rw-r--r-- | crypto/src/asn1/Asn1Encodable.cs | 2 | ||||
-rw-r--r-- | crypto/src/asn1/Asn1EncodableVector.cs | 248 | ||||
-rw-r--r-- | crypto/src/asn1/Asn1TaggedObject.cs | 2 | ||||
-rw-r--r-- | crypto/src/asn1/DerObjectIdentifier.cs | 30 | ||||
-rw-r--r-- | crypto/src/asn1/cms/Evidence.cs | 38 | ||||
-rw-r--r-- | crypto/src/util/Arrays.cs | 14 | ||||
-rw-r--r-- | crypto/test/src/asn1/test/LinkedCertificateTest.cs | 2 |
7 files changed, 232 insertions, 104 deletions
diff --git a/crypto/src/asn1/Asn1Encodable.cs b/crypto/src/asn1/Asn1Encodable.cs index e3dd9a14c..12628082d 100644 --- a/crypto/src/asn1/Asn1Encodable.cs +++ b/crypto/src/asn1/Asn1Encodable.cs @@ -70,7 +70,7 @@ namespace Org.BouncyCastle.Asn1 Asn1Object o1 = ToAsn1Object(); Asn1Object o2 = other.ToAsn1Object(); - return o1 == o2 || o1.CallAsn1Equals(o2); + return o1 == o2 || (null != o2 && o1.CallAsn1Equals(o2)); } public abstract Asn1Object ToAsn1Object(); diff --git a/crypto/src/asn1/Asn1EncodableVector.cs b/crypto/src/asn1/Asn1EncodableVector.cs index 8a97e8b4f..987aa5298 100644 --- a/crypto/src/asn1/Asn1EncodableVector.cs +++ b/crypto/src/asn1/Asn1EncodableVector.cs @@ -1,101 +1,191 @@ using System; using System.Collections; -using Org.BouncyCastle.Utilities; - namespace Org.BouncyCastle.Asn1 { + /** + * Mutable class for building ASN.1 constructed objects such as SETs or SEQUENCEs. + */ public class Asn1EncodableVector - : IEnumerable + : IEnumerable { - private IList v = Platform.CreateArrayList(); - - public static Asn1EncodableVector FromEnumerable( - IEnumerable e) - { - Asn1EncodableVector v = new Asn1EncodableVector(); - foreach (Asn1Encodable obj in e) - { - v.Add(obj); - } - return v; - } - -// public Asn1EncodableVector() -// { -// } - - public Asn1EncodableVector( - params Asn1Encodable[] v) - { - Add(v); - } - -// public void Add( -// Asn1Encodable obj) -// { -// v.Add(obj); -// } - - public void Add( - params Asn1Encodable[] objs) - { - foreach (Asn1Encodable obj in objs) - { - v.Add(obj); - } - } - - public void AddOptional( - params Asn1Encodable[] objs) - { - if (objs != null) - { - foreach (Asn1Encodable obj in objs) - { - if (obj != null) - { - v.Add(obj); - } - } - } - } + internal static readonly Asn1Encodable[] EmptyElements = new Asn1Encodable[0]; + + private const int DefaultCapacity = 10; + + private Asn1Encodable[] elements; + private int elementCount; + private bool copyOnWrite; + + public static Asn1EncodableVector FromEnumerable(IEnumerable e) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + foreach (Asn1Encodable obj in e) + { + v.Add(obj); + } + return v; + } + + public Asn1EncodableVector() + : this(DefaultCapacity) + { + } + + public Asn1EncodableVector(int initialCapacity) + { + if (initialCapacity < 0) + throw new ArgumentException("must not be negative", "initialCapacity"); + + this.elements = (initialCapacity == 0) ? EmptyElements : new Asn1Encodable[initialCapacity]; + this.elementCount = 0; + this.copyOnWrite = false; + } + + public Asn1EncodableVector(params Asn1Encodable[] v) + : this() + { + Add(v); + } + + public void Add(Asn1Encodable element) + { + if (null == element) + throw new ArgumentNullException("element"); + + int capacity = elements.Length; + int minCapacity = elementCount + 1; + if ((minCapacity > capacity) | copyOnWrite) + { + Reallocate(minCapacity); + } + + this.elements[elementCount] = element; + this.elementCount = minCapacity; + } + + public void Add(params Asn1Encodable[] objs) + { + foreach (Asn1Encodable obj in objs) + { + Add(obj); + } + } + + public void AddOptional(params Asn1Encodable[] objs) + { + if (objs != null) + { + foreach (Asn1Encodable obj in objs) + { + if (obj != null) + { + Add(obj); + } + } + } + } public void AddOptionalTagged(bool isExplicit, int tagNo, Asn1Encodable obj) { if (null != obj) { - v.Add(new DerTaggedObject(isExplicit, tagNo, obj)); + Add(new DerTaggedObject(isExplicit, tagNo, obj)); } } - public Asn1Encodable this[ - int index] - { - get { return (Asn1Encodable) v[index]; } - } + public void AddAll(Asn1EncodableVector other) + { + if (null == other) + throw new ArgumentNullException("other"); - [Obsolete("Use 'object[index]' syntax instead")] - public Asn1Encodable Get( - int index) + int otherElementCount = other.Count; + if (otherElementCount < 1) + return; + + int capacity = elements.Length; + int minCapacity = elementCount + otherElementCount; + if ((minCapacity > capacity) | copyOnWrite) + { + Reallocate(minCapacity); + } + + int i = 0; + do + { + Asn1Encodable otherElement = other[i]; + if (null == otherElement) + throw new NullReferenceException("'other' elements cannot be null"); + + this.elements[elementCount + i] = otherElement; + } + while (++i < otherElementCount); + + this.elementCount = minCapacity; + } + + public Asn1Encodable this[int index] { - return this[index]; + get + { + if (index >= elementCount) + throw new IndexOutOfRangeException(index + " >= " + elementCount); + + return elements[index]; + } } - [Obsolete("Use 'Count' property instead")] - public int Size - { - get { return v.Count; } - } + public int Count + { + get { return elementCount; } + } - public int Count - { - get { return v.Count; } - } + public IEnumerator GetEnumerator() + { + return CopyElements().GetEnumerator(); + } - public IEnumerator GetEnumerator() - { - return v.GetEnumerator(); - } - } + internal Asn1Encodable[] CopyElements() + { + if (0 == elementCount) + return EmptyElements; + + Asn1Encodable[] copy = new Asn1Encodable[elementCount]; + Array.Copy(elements, 0, copy, 0, elementCount); + return copy; + } + + internal Asn1Encodable[] TakeElements() + { + if (0 == elementCount) + return EmptyElements; + + if (elements.Length == elementCount) + { + this.copyOnWrite = true; + return elements; + } + + Asn1Encodable[] copy = new Asn1Encodable[elementCount]; + Array.Copy(elements, 0, copy, 0, elementCount); + return copy; + } + + private void Reallocate(int minCapacity) + { + int oldCapacity = elements.Length; + int newCapacity = System.Math.Max(oldCapacity, minCapacity + (minCapacity >> 1)); + + Asn1Encodable[] copy = new Asn1Encodable[newCapacity]; + Array.Copy(elements, 0, copy, 0, elementCount); + + this.elements = copy; + this.copyOnWrite = false; + } + + internal static Asn1Encodable[] CloneElements(Asn1Encodable[] elements) + { + return elements.Length < 1 ? EmptyElements : (Asn1Encodable[])elements.Clone(); + } + } } diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs index a6d4b2c28..14b1bc65f 100644 --- a/crypto/src/asn1/Asn1TaggedObject.cs +++ b/crypto/src/asn1/Asn1TaggedObject.cs @@ -33,7 +33,7 @@ namespace Org.BouncyCastle.Asn1 { if (explicitly) { - return (Asn1TaggedObject) obj.GetObject(); + return GetInstance(obj.GetObject()); } throw new ArgumentException("implicitly tagged tagged object"); diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs index 1c8032f45..fb38d5f05 100644 --- a/crypto/src/asn1/DerObjectIdentifier.cs +++ b/crypto/src/asn1/DerObjectIdentifier.cs @@ -210,36 +210,36 @@ namespace Org.BouncyCastle.Asn1 return identifier; } - private static bool IsValidBranchID( - string branchID, int start) + private static bool IsValidBranchID(string branchID, int start) { - bool periodAllowed = false; + int digitCount = 0; int pos = branchID.Length; while (--pos >= start) { char ch = branchID[pos]; - // TODO Leading zeroes? - if ('0' <= ch && ch <= '9') - { - periodAllowed = true; - continue; - } - if (ch == '.') { - if (!periodAllowed) + if (0 == digitCount || (digitCount > 1 && branchID[pos + 1] == '0')) return false; - periodAllowed = false; - continue; + digitCount = 0; + } + else if ('0' <= ch && ch <= '9') + { + ++digitCount; } + else + { + return false; + } + } + if (0 == digitCount || (digitCount > 1 && branchID[pos + 1] == '0')) return false; - } - return periodAllowed; + return true; } private static bool IsValidIdentifier(string identifier) diff --git a/crypto/src/asn1/cms/Evidence.cs b/crypto/src/asn1/cms/Evidence.cs index 8374aed55..b12f090a9 100644 --- a/crypto/src/asn1/cms/Evidence.cs +++ b/crypto/src/asn1/cms/Evidence.cs @@ -8,6 +8,7 @@ namespace Org.BouncyCastle.Asn1.Cms : Asn1Encodable, IAsn1Choice { private TimeStampTokenEvidence tstEvidence; + private Asn1Sequence otherEvidence; public Evidence(TimeStampTokenEvidence tstEvidence) { @@ -16,11 +17,23 @@ namespace Org.BouncyCastle.Asn1.Cms private Evidence(Asn1TaggedObject tagged) { - if (tagged.TagNo == 0) - { - this.tstEvidence = TimeStampTokenEvidence.GetInstance(tagged, false); - } - } + if (tagged.TagNo == 0) + { + this.tstEvidence = TimeStampTokenEvidence.GetInstance(tagged, false); + } + //else if (tagged.TagNo == 1) + //{ + // this.ersEvidence = EvidenceRecord.GetInstance(tagged, false); + //} + else if (tagged.TagNo == 2) + { + this.otherEvidence = Asn1Sequence.GetInstance(tagged, false); + } + else + { + throw new ArgumentException("unknown tag in Evidence", "tagged"); + } + } public static Evidence GetInstance(object obj) { @@ -33,17 +46,28 @@ namespace Org.BouncyCastle.Asn1.Cms throw new ArgumentException("Unknown object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } + public static Evidence GetInstance(Asn1TaggedObject obj, bool isExplicit) + { + return GetInstance(obj.GetObject()); // must be explicitly tagged + } + public virtual TimeStampTokenEvidence TstEvidence { get { return tstEvidence; } } + //public EvidenceRecord ErsEvidence + //{ + // get { return ersEvidence; } + //} + public override Asn1Object ToAsn1Object() { if (tstEvidence != null) return new DerTaggedObject(false, 0, tstEvidence); - - return null; + //if (ersEvidence != null) + // return new DerTaggedObject(false, 1, ersEvidence); + return new DerTaggedObject(false, 2, otherEvidence); } } } diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index aa8d31df4..5d62d7174 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -721,5 +721,19 @@ namespace Org.BouncyCastle.Utilities return result; } + + public static bool IsNullOrContainsNull(object[] array) + { + if (null == array) + return true; + + int count = array.Length; + for (int i = 0; i < count; ++i) + { + if (null == array[i]) + return true; + } + return false; + } } } diff --git a/crypto/test/src/asn1/test/LinkedCertificateTest.cs b/crypto/test/src/asn1/test/LinkedCertificateTest.cs index 416c048c0..1ac5ab0fd 100644 --- a/crypto/test/src/asn1/test/LinkedCertificateTest.cs +++ b/crypto/test/src/asn1/test/LinkedCertificateTest.cs @@ -48,7 +48,7 @@ namespace Org.BouncyCastle.Asn1.Tests Fail("getInstance() failed to detect bad object."); } - catch (ArgumentException e) + catch (ArgumentException) { // expected } |