ASN1StreamParser.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.IO;
  4. namespace Org.BouncyCastle.Asn1
  5. {
  6. public class Asn1StreamParser
  7. {
  8. private readonly Stream _in;
  9. private readonly int _limit;
  10. private readonly byte[][] tmpBuffers;
  11. public Asn1StreamParser(
  12. Stream inStream)
  13. : this(inStream, Asn1InputStream.FindLimit(inStream))
  14. {
  15. }
  16. public Asn1StreamParser(
  17. Stream inStream,
  18. int limit)
  19. {
  20. if (!inStream.CanRead)
  21. throw new ArgumentException("Expected stream to be readable", "inStream");
  22. this._in = inStream;
  23. this._limit = limit;
  24. this.tmpBuffers = new byte[16][];
  25. }
  26. public Asn1StreamParser(
  27. byte[] encoding)
  28. : this(new MemoryStream(encoding, false), encoding.Length)
  29. {
  30. }
  31. internal IAsn1Convertible ReadIndef(int tagValue)
  32. {
  33. // Note: INDEF => CONSTRUCTED
  34. // TODO There are other tags that may be constructed (e.g. BIT_STRING)
  35. switch (tagValue)
  36. {
  37. case Asn1Tags.External:
  38. return new DerExternalParser(this);
  39. case Asn1Tags.OctetString:
  40. return new BerOctetStringParser(this);
  41. case Asn1Tags.Sequence:
  42. return new BerSequenceParser(this);
  43. case Asn1Tags.Set:
  44. return new BerSetParser(this);
  45. default:
  46. throw new Asn1Exception("unknown BER object encountered: 0x" + tagValue.ToString("X"));
  47. }
  48. }
  49. internal IAsn1Convertible ReadImplicit(bool constructed, int tag)
  50. {
  51. if (_in is IndefiniteLengthInputStream)
  52. {
  53. if (!constructed)
  54. throw new IOException("indefinite length primitive encoding encountered");
  55. return ReadIndef(tag);
  56. }
  57. if (constructed)
  58. {
  59. switch (tag)
  60. {
  61. case Asn1Tags.Set:
  62. return new DerSetParser(this);
  63. case Asn1Tags.Sequence:
  64. return new DerSequenceParser(this);
  65. case Asn1Tags.OctetString:
  66. return new BerOctetStringParser(this);
  67. }
  68. }
  69. else
  70. {
  71. switch (tag)
  72. {
  73. case Asn1Tags.Set:
  74. throw new Asn1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
  75. case Asn1Tags.Sequence:
  76. throw new Asn1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
  77. case Asn1Tags.OctetString:
  78. return new DerOctetStringParser((DefiniteLengthInputStream)_in);
  79. }
  80. }
  81. throw new Asn1Exception("implicit tagging not implemented");
  82. }
  83. internal Asn1Object ReadTaggedObject(bool constructed, int tag)
  84. {
  85. if (!constructed)
  86. {
  87. // Note: !CONSTRUCTED => IMPLICIT
  88. DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
  89. return new DerTaggedObject(false, tag, new DerOctetString(defIn.ToArray()));
  90. }
  91. Asn1EncodableVector v = ReadVector();
  92. if (_in is IndefiniteLengthInputStream)
  93. {
  94. return v.Count == 1
  95. ? new BerTaggedObject(true, tag, v[0])
  96. : new BerTaggedObject(false, tag, BerSequence.FromVector(v));
  97. }
  98. return v.Count == 1
  99. ? new DerTaggedObject(true, tag, v[0])
  100. : new DerTaggedObject(false, tag, DerSequence.FromVector(v));
  101. }
  102. public virtual IAsn1Convertible ReadObject()
  103. {
  104. int tag = _in.ReadByte();
  105. if (tag == -1)
  106. return null;
  107. // turn of looking for "00" while we resolve the tag
  108. Set00Check(false);
  109. //
  110. // calculate tag number
  111. //
  112. int tagNo = Asn1InputStream.ReadTagNumber(_in, tag);
  113. bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
  114. //
  115. // calculate length
  116. //
  117. int length = Asn1InputStream.ReadLength(_in, _limit);
  118. if (length < 0) // indefinite length method
  119. {
  120. if (!isConstructed)
  121. throw new IOException("indefinite length primitive encoding encountered");
  122. IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
  123. Asn1StreamParser sp = new Asn1StreamParser(indIn, _limit);
  124. if ((tag & Asn1Tags.Application) != 0)
  125. {
  126. return new BerApplicationSpecificParser(tagNo, sp);
  127. }
  128. if ((tag & Asn1Tags.Tagged) != 0)
  129. {
  130. return new BerTaggedObjectParser(true, tagNo, sp);
  131. }
  132. return sp.ReadIndef(tagNo);
  133. }
  134. else
  135. {
  136. DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
  137. if ((tag & Asn1Tags.Application) != 0)
  138. {
  139. return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
  140. }
  141. if ((tag & Asn1Tags.Tagged) != 0)
  142. {
  143. return new BerTaggedObjectParser(isConstructed, tagNo, new Asn1StreamParser(defIn));
  144. }
  145. if (isConstructed)
  146. {
  147. // TODO There are other tags that may be constructed (e.g. BitString)
  148. switch (tagNo)
  149. {
  150. case Asn1Tags.OctetString:
  151. //
  152. // yes, people actually do this...
  153. //
  154. return new BerOctetStringParser(new Asn1StreamParser(defIn));
  155. case Asn1Tags.Sequence:
  156. return new DerSequenceParser(new Asn1StreamParser(defIn));
  157. case Asn1Tags.Set:
  158. return new DerSetParser(new Asn1StreamParser(defIn));
  159. case Asn1Tags.External:
  160. return new DerExternalParser(new Asn1StreamParser(defIn));
  161. default:
  162. throw new IOException("unknown tag " + tagNo + " encountered");
  163. }
  164. }
  165. // Some primitive encodings can be handled by parsers too...
  166. switch (tagNo)
  167. {
  168. case Asn1Tags.OctetString:
  169. return new DerOctetStringParser(defIn);
  170. }
  171. try
  172. {
  173. return Asn1InputStream.CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers);
  174. }
  175. catch (ArgumentException e)
  176. {
  177. throw new Asn1Exception("corrupted stream detected", e);
  178. }
  179. }
  180. }
  181. private void Set00Check(
  182. bool enabled)
  183. {
  184. if (_in is IndefiniteLengthInputStream)
  185. {
  186. ((IndefiniteLengthInputStream) _in).SetEofOn00(enabled);
  187. }
  188. }
  189. internal Asn1EncodableVector ReadVector()
  190. {
  191. Asn1EncodableVector v = new Asn1EncodableVector();
  192. IAsn1Convertible obj;
  193. while ((obj = ReadObject()) != null)
  194. {
  195. v.Add(obj.ToAsn1Object());
  196. }
  197. return v;
  198. }
  199. }
  200. }
  201. #endif