Asn1Sequence.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. using Org.BouncyCastle.Utilities;
  6. using Org.BouncyCastle.Utilities.Collections;
  7. namespace Org.BouncyCastle.Asn1
  8. {
  9. public abstract class Asn1Sequence
  10. : Asn1Object, IEnumerable
  11. {
  12. private readonly IList seq;
  13. /**
  14. * return an Asn1Sequence from the given object.
  15. *
  16. * @param obj the object we want converted.
  17. * @exception ArgumentException if the object cannot be converted.
  18. */
  19. public static Asn1Sequence GetInstance(
  20. object obj)
  21. {
  22. if (obj == null || obj is Asn1Sequence)
  23. {
  24. return (Asn1Sequence)obj;
  25. }
  26. else if (obj is Asn1SequenceParser)
  27. {
  28. return Asn1Sequence.GetInstance(((Asn1SequenceParser)obj).ToAsn1Object());
  29. }
  30. else if (obj is byte[])
  31. {
  32. try
  33. {
  34. return Asn1Sequence.GetInstance(FromByteArray((byte[])obj));
  35. }
  36. catch (IOException e)
  37. {
  38. throw new ArgumentException("failed to construct sequence from byte[]: " + e.Message);
  39. }
  40. }
  41. else if (obj is Asn1Encodable)
  42. {
  43. Asn1Object primitive = ((Asn1Encodable)obj).ToAsn1Object();
  44. if (primitive is Asn1Sequence)
  45. {
  46. return (Asn1Sequence)primitive;
  47. }
  48. }
  49. throw new ArgumentException("Unknown object in GetInstance: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(obj), "obj");
  50. }
  51. /**
  52. * Return an ASN1 sequence from a tagged object. There is a special
  53. * case here, if an object appears to have been explicitly tagged on
  54. * reading but we were expecting it to be implicitly tagged in the
  55. * normal course of events it indicates that we lost the surrounding
  56. * sequence - so we need to add it back (this will happen if the tagged
  57. * object is a sequence that contains other sequences). If you are
  58. * dealing with implicitly tagged sequences you really <b>should</b>
  59. * be using this method.
  60. *
  61. * @param obj the tagged object.
  62. * @param explicitly true if the object is meant to be explicitly tagged,
  63. * false otherwise.
  64. * @exception ArgumentException if the tagged object cannot
  65. * be converted.
  66. */
  67. public static Asn1Sequence GetInstance(
  68. Asn1TaggedObject obj,
  69. bool explicitly)
  70. {
  71. Asn1Object inner = obj.GetObject();
  72. if (explicitly)
  73. {
  74. if (!obj.IsExplicit())
  75. throw new ArgumentException("object implicit - explicit expected.");
  76. return (Asn1Sequence) inner;
  77. }
  78. //
  79. // constructed object which appears to be explicitly tagged
  80. // when it should be implicit means we have to add the
  81. // surrounding sequence.
  82. //
  83. if (obj.IsExplicit())
  84. {
  85. if (obj is BerTaggedObject)
  86. {
  87. return new BerSequence(inner);
  88. }
  89. return new DerSequence(inner);
  90. }
  91. if (inner is Asn1Sequence)
  92. {
  93. return (Asn1Sequence) inner;
  94. }
  95. throw new ArgumentException("Unknown object in GetInstance: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(obj), "obj");
  96. }
  97. protected internal Asn1Sequence(
  98. int capacity)
  99. {
  100. seq = Org.BouncyCastle.Utilities.Platform.CreateArrayList(capacity);
  101. }
  102. public virtual IEnumerator GetEnumerator()
  103. {
  104. return seq.GetEnumerator();
  105. }
  106. [Obsolete("Use GetEnumerator() instead")]
  107. public IEnumerator GetObjects()
  108. {
  109. return GetEnumerator();
  110. }
  111. private class Asn1SequenceParserImpl
  112. : Asn1SequenceParser
  113. {
  114. private readonly Asn1Sequence outer;
  115. private readonly int max;
  116. private int index;
  117. public Asn1SequenceParserImpl(
  118. Asn1Sequence outer)
  119. {
  120. this.outer = outer;
  121. this.max = outer.Count;
  122. }
  123. public IAsn1Convertible ReadObject()
  124. {
  125. if (index == max)
  126. return null;
  127. Asn1Encodable obj = outer[index++];
  128. if (obj is Asn1Sequence)
  129. return ((Asn1Sequence)obj).Parser;
  130. if (obj is Asn1Set)
  131. return ((Asn1Set)obj).Parser;
  132. // NB: Asn1OctetString implements Asn1OctetStringParser directly
  133. // if (obj is Asn1OctetString)
  134. // return ((Asn1OctetString)obj).Parser;
  135. return obj;
  136. }
  137. public Asn1Object ToAsn1Object()
  138. {
  139. return outer;
  140. }
  141. }
  142. public virtual Asn1SequenceParser Parser
  143. {
  144. get { return new Asn1SequenceParserImpl(this); }
  145. }
  146. /**
  147. * return the object at the sequence position indicated by index.
  148. *
  149. * @param index the sequence number (starting at zero) of the object
  150. * @return the object at the sequence position indicated by index.
  151. */
  152. public virtual Asn1Encodable this[int index]
  153. {
  154. get { return (Asn1Encodable) seq[index]; }
  155. }
  156. [Obsolete("Use 'object[index]' syntax instead")]
  157. public Asn1Encodable GetObjectAt(
  158. int index)
  159. {
  160. return this[index];
  161. }
  162. [Obsolete("Use 'Count' property instead")]
  163. public int Size
  164. {
  165. get { return Count; }
  166. }
  167. public virtual int Count
  168. {
  169. get { return seq.Count; }
  170. }
  171. protected override int Asn1GetHashCode()
  172. {
  173. int hc = Count;
  174. foreach (object o in this)
  175. {
  176. hc *= 17;
  177. if (o == null)
  178. {
  179. hc ^= DerNull.Instance.GetHashCode();
  180. }
  181. else
  182. {
  183. hc ^= o.GetHashCode();
  184. }
  185. }
  186. return hc;
  187. }
  188. protected override bool Asn1Equals(
  189. Asn1Object asn1Object)
  190. {
  191. Asn1Sequence other = asn1Object as Asn1Sequence;
  192. if (other == null)
  193. return false;
  194. if (Count != other.Count)
  195. return false;
  196. IEnumerator s1 = GetEnumerator();
  197. IEnumerator s2 = other.GetEnumerator();
  198. while (s1.MoveNext() && s2.MoveNext())
  199. {
  200. Asn1Object o1 = GetCurrent(s1).ToAsn1Object();
  201. Asn1Object o2 = GetCurrent(s2).ToAsn1Object();
  202. if (!o1.Equals(o2))
  203. return false;
  204. }
  205. return true;
  206. }
  207. private Asn1Encodable GetCurrent(IEnumerator e)
  208. {
  209. Asn1Encodable encObj = (Asn1Encodable)e.Current;
  210. // unfortunately null was allowed as a substitute for DER null
  211. if (encObj == null)
  212. return DerNull.Instance;
  213. return encObj;
  214. }
  215. protected internal void AddObject(
  216. Asn1Encodable obj)
  217. {
  218. seq.Add(obj);
  219. }
  220. public override string ToString()
  221. {
  222. return CollectionUtilities.ToString(seq);
  223. }
  224. }
  225. }
  226. #endif