DerApplicationSpecific.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.IO;
  4. using Org.BouncyCastle.Utilities;
  5. namespace Org.BouncyCastle.Asn1
  6. {
  7. /**
  8. * Base class for an application specific object
  9. */
  10. public class DerApplicationSpecific
  11. : Asn1Object
  12. {
  13. private readonly bool isConstructed;
  14. private readonly int tag;
  15. private readonly byte[] octets;
  16. internal DerApplicationSpecific(
  17. bool isConstructed,
  18. int tag,
  19. byte[] octets)
  20. {
  21. this.isConstructed = isConstructed;
  22. this.tag = tag;
  23. this.octets = octets;
  24. }
  25. public DerApplicationSpecific(
  26. int tag,
  27. byte[] octets)
  28. : this(false, tag, octets)
  29. {
  30. }
  31. public DerApplicationSpecific(
  32. int tag,
  33. Asn1Encodable obj)
  34. : this(true, tag, obj)
  35. {
  36. }
  37. public DerApplicationSpecific(
  38. bool isExplicit,
  39. int tag,
  40. Asn1Encodable obj)
  41. {
  42. Asn1Object asn1Obj = obj.ToAsn1Object();
  43. byte[] data = asn1Obj.GetDerEncoded();
  44. this.isConstructed = Asn1TaggedObject.IsConstructed(isExplicit, asn1Obj);
  45. this.tag = tag;
  46. if (isExplicit)
  47. {
  48. this.octets = data;
  49. }
  50. else
  51. {
  52. int lenBytes = GetLengthOfHeader(data);
  53. byte[] tmp = new byte[data.Length - lenBytes];
  54. Array.Copy(data, lenBytes, tmp, 0, tmp.Length);
  55. this.octets = tmp;
  56. }
  57. }
  58. public DerApplicationSpecific(
  59. int tagNo,
  60. Asn1EncodableVector vec)
  61. {
  62. this.tag = tagNo;
  63. this.isConstructed = true;
  64. MemoryStream bOut = new MemoryStream();
  65. for (int i = 0; i != vec.Count; i++)
  66. {
  67. try
  68. {
  69. byte[] bs = vec[i].GetDerEncoded();
  70. bOut.Write(bs, 0, bs.Length);
  71. }
  72. catch (IOException e)
  73. {
  74. throw new InvalidOperationException("malformed object", e);
  75. }
  76. }
  77. this.octets = bOut.ToArray();
  78. }
  79. private int GetLengthOfHeader(
  80. byte[] data)
  81. {
  82. int length = data[1]; // TODO: assumes 1 byte tag
  83. if (length == 0x80)
  84. {
  85. return 2; // indefinite-length encoding
  86. }
  87. if (length > 127)
  88. {
  89. int size = length & 0x7f;
  90. // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
  91. if (size > 4)
  92. {
  93. throw new InvalidOperationException("DER length more than 4 bytes: " + size);
  94. }
  95. return size + 2;
  96. }
  97. return 2;
  98. }
  99. public bool IsConstructed()
  100. {
  101. return isConstructed;
  102. }
  103. public byte[] GetContents()
  104. {
  105. return octets;
  106. }
  107. public int ApplicationTag
  108. {
  109. get { return tag; }
  110. }
  111. /**
  112. * Return the enclosed object assuming explicit tagging.
  113. *
  114. * @return the resulting object
  115. * @throws IOException if reconstruction fails.
  116. */
  117. public Asn1Object GetObject()
  118. {
  119. return FromByteArray(GetContents());
  120. }
  121. /**
  122. * Return the enclosed object assuming implicit tagging.
  123. *
  124. * @param derTagNo the type tag that should be applied to the object's contents.
  125. * @return the resulting object
  126. * @throws IOException if reconstruction fails.
  127. */
  128. public Asn1Object GetObject(
  129. int derTagNo)
  130. {
  131. if (derTagNo >= 0x1f)
  132. throw new IOException("unsupported tag number");
  133. byte[] orig = this.GetEncoded();
  134. byte[] tmp = ReplaceTagNumber(derTagNo, orig);
  135. if ((orig[0] & Asn1Tags.Constructed) != 0)
  136. {
  137. tmp[0] |= Asn1Tags.Constructed;
  138. }
  139. return FromByteArray(tmp);
  140. }
  141. internal override void Encode(
  142. DerOutputStream derOut)
  143. {
  144. int classBits = Asn1Tags.Application;
  145. if (isConstructed)
  146. {
  147. classBits |= Asn1Tags.Constructed;
  148. }
  149. derOut.WriteEncoded(classBits, tag, octets);
  150. }
  151. protected override bool Asn1Equals(
  152. Asn1Object asn1Object)
  153. {
  154. DerApplicationSpecific other = asn1Object as DerApplicationSpecific;
  155. if (other == null)
  156. return false;
  157. return this.isConstructed == other.isConstructed
  158. && this.tag == other.tag
  159. && Arrays.AreEqual(this.octets, other.octets);
  160. }
  161. protected override int Asn1GetHashCode()
  162. {
  163. return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(octets);
  164. }
  165. private byte[] ReplaceTagNumber(
  166. int newTag,
  167. byte[] input)
  168. {
  169. int tagNo = input[0] & 0x1f;
  170. int index = 1;
  171. //
  172. // with tagged object tag number is bottom 5 bits, or stored at the start of the content
  173. //
  174. if (tagNo == 0x1f)
  175. {
  176. tagNo = 0;
  177. int b = input[index++] & 0xff;
  178. // X.690-0207 8.1.2.4.2
  179. // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
  180. if ((b & 0x7f) == 0) // Note: -1 will pass
  181. {
  182. throw new InvalidOperationException("corrupted stream - invalid high tag number found");
  183. }
  184. while ((b >= 0) && ((b & 0x80) != 0))
  185. {
  186. tagNo |= (b & 0x7f);
  187. tagNo <<= 7;
  188. b = input[index++] & 0xff;
  189. }
  190. tagNo |= (b & 0x7f);
  191. }
  192. byte[] tmp = new byte[input.Length - index + 1];
  193. Array.Copy(input, index, tmp, 1, tmp.Length - 1);
  194. tmp[0] = (byte)newTag;
  195. return tmp;
  196. }
  197. }
  198. }
  199. #endif