DERExternal.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.IO;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  6. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1
  7. {
  8. /**
  9. * Class representing the DER-type External
  10. */
  11. public class DerExternal
  12. : Asn1Object
  13. {
  14. internal class Meta : Asn1UniversalType
  15. {
  16. internal static readonly Asn1UniversalType Instance = new Meta();
  17. private Meta() : base(typeof(DerExternal), Asn1Tags.External) {}
  18. internal override Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
  19. {
  20. return sequence.ToAsn1External();
  21. }
  22. }
  23. public static DerExternal GetInstance(object obj)
  24. {
  25. if (obj == null)
  26. return null;
  27. if (obj is DerExternal derExternal)
  28. return derExternal;
  29. if (obj is IAsn1Convertible asn1Convertible)
  30. {
  31. Asn1Object asn1Object = asn1Convertible.ToAsn1Object();
  32. if (asn1Object is DerExternal converted)
  33. return converted;
  34. }
  35. else if (obj is byte[] bytes)
  36. {
  37. try
  38. {
  39. return (DerExternal)Meta.Instance.FromByteArray(bytes);
  40. }
  41. catch (IOException e)
  42. {
  43. throw new ArgumentException("failed to construct external from byte[]: " + e.Message);
  44. }
  45. }
  46. throw new ArgumentException("illegal object in GetInstance: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(obj), "obj");
  47. }
  48. public static DerExternal GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
  49. {
  50. return (DerExternal)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
  51. }
  52. private readonly DerObjectIdentifier directReference;
  53. private readonly DerInteger indirectReference;
  54. private readonly Asn1ObjectDescriptor dataValueDescriptor;
  55. private readonly int encoding;
  56. private readonly Asn1Object externalContent;
  57. public DerExternal(Asn1EncodableVector vector)
  58. : this(new DerSequence(vector))
  59. {
  60. }
  61. public DerExternal(Asn1Sequence sequence)
  62. {
  63. int offset = 0;
  64. Asn1Object asn1 = GetObjFromSequence(sequence, offset);
  65. if (asn1 is DerObjectIdentifier)
  66. {
  67. directReference = (DerObjectIdentifier)asn1;
  68. asn1 = GetObjFromSequence(sequence, ++offset);
  69. }
  70. if (asn1 is DerInteger)
  71. {
  72. indirectReference = (DerInteger)asn1;
  73. asn1 = GetObjFromSequence(sequence, ++offset);
  74. }
  75. if (!(asn1 is Asn1TaggedObject))
  76. {
  77. dataValueDescriptor = (Asn1ObjectDescriptor)asn1;
  78. asn1 = GetObjFromSequence(sequence, ++offset);
  79. }
  80. if (sequence.Count != offset + 1)
  81. throw new ArgumentException("input sequence too large", "sequence");
  82. if (!(asn1 is Asn1TaggedObject))
  83. throw new ArgumentException(
  84. "No tagged object found in sequence. Structure doesn't seem to be of type External", "sequence");
  85. Asn1TaggedObject obj = (Asn1TaggedObject)asn1;
  86. this.encoding = CheckEncoding(obj.TagNo);
  87. this.externalContent = GetExternalContent(obj);
  88. }
  89. /**
  90. * Creates a new instance of DerExternal
  91. * See X.690 for more informations about the meaning of these parameters
  92. * @param directReference The direct reference or <code>null</code> if not set.
  93. * @param indirectReference The indirect reference or <code>null</code> if not set.
  94. * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
  95. * @param externalData The external data in its encoded form.
  96. */
  97. public DerExternal(DerObjectIdentifier directReference, DerInteger indirectReference,
  98. Asn1ObjectDescriptor dataValueDescriptor, DerTaggedObject externalData)
  99. {
  100. this.directReference = directReference;
  101. this.indirectReference = indirectReference;
  102. this.dataValueDescriptor = dataValueDescriptor;
  103. this.encoding = CheckEncoding(externalData.TagNo);
  104. this.externalContent = GetExternalContent(externalData);
  105. }
  106. /**
  107. * Creates a new instance of DerExternal.
  108. * See X.690 for more informations about the meaning of these parameters
  109. * @param directReference The direct reference or <code>null</code> if not set.
  110. * @param indirectReference The indirect reference or <code>null</code> if not set.
  111. * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
  112. * @param encoding The encoding to be used for the external data
  113. * @param externalData The external data
  114. */
  115. public DerExternal(DerObjectIdentifier directReference, DerInteger indirectReference,
  116. Asn1ObjectDescriptor dataValueDescriptor, int encoding, Asn1Object externalData)
  117. {
  118. this.directReference = directReference;
  119. this.indirectReference = indirectReference;
  120. this.dataValueDescriptor = dataValueDescriptor;
  121. this.encoding = CheckEncoding(encoding);
  122. this.externalContent = CheckExternalContent(encoding, externalData);
  123. }
  124. internal Asn1Sequence BuildSequence()
  125. {
  126. Asn1EncodableVector v = new Asn1EncodableVector(4);
  127. v.AddOptional(directReference, indirectReference, dataValueDescriptor);
  128. v.Add(new DerTaggedObject(0 == encoding, encoding, externalContent));
  129. return new DerSequence(v);
  130. }
  131. internal override IAsn1Encoding GetEncoding(int encoding)
  132. {
  133. return BuildSequence().GetEncodingImplicit(encoding, Asn1Tags.Universal, Asn1Tags.External);
  134. }
  135. internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
  136. {
  137. return BuildSequence().GetEncodingImplicit(encoding, tagClass, tagNo);
  138. }
  139. protected override int Asn1GetHashCode()
  140. {
  141. return Objects.GetHashCode(this.directReference)
  142. ^ Objects.GetHashCode(this.indirectReference)
  143. ^ Objects.GetHashCode(this.dataValueDescriptor)
  144. ^ this.encoding
  145. ^ this.externalContent.GetHashCode();
  146. }
  147. protected override bool Asn1Equals(Asn1Object asn1Object)
  148. {
  149. DerExternal that = asn1Object as DerExternal;
  150. return null != that
  151. && Equals(this.directReference, that.directReference)
  152. && Equals(this.indirectReference, that.indirectReference)
  153. && Equals(this.dataValueDescriptor, that.dataValueDescriptor)
  154. && this.encoding == that.encoding
  155. && this.externalContent.Equals(that.externalContent);
  156. }
  157. public Asn1ObjectDescriptor DataValueDescriptor
  158. {
  159. get { return dataValueDescriptor; }
  160. }
  161. public DerObjectIdentifier DirectReference
  162. {
  163. get { return directReference; }
  164. }
  165. /**
  166. * The encoding of the content. Valid values are
  167. * <ul>
  168. * <li><code>0</code> single-ASN1-type</li>
  169. * <li><code>1</code> OCTET STRING</li>
  170. * <li><code>2</code> BIT STRING</li>
  171. * </ul>
  172. */
  173. public int Encoding
  174. {
  175. get { return encoding; }
  176. }
  177. public Asn1Object ExternalContent
  178. {
  179. get { return externalContent; }
  180. }
  181. public DerInteger IndirectReference
  182. {
  183. get { return indirectReference; }
  184. }
  185. private static Asn1ObjectDescriptor CheckDataValueDescriptor(Asn1Object dataValueDescriptor)
  186. {
  187. if (dataValueDescriptor is Asn1ObjectDescriptor)
  188. return (Asn1ObjectDescriptor)dataValueDescriptor;
  189. if (dataValueDescriptor is DerGraphicString)
  190. return new Asn1ObjectDescriptor((DerGraphicString)dataValueDescriptor);
  191. throw new ArgumentException("incompatible type for data-value-descriptor", "dataValueDescriptor");
  192. }
  193. private static int CheckEncoding(int encoding)
  194. {
  195. if (encoding < 0 || encoding > 2)
  196. throw new InvalidOperationException("invalid encoding value: " + encoding);
  197. return encoding;
  198. }
  199. private static Asn1Object CheckExternalContent(int tagNo, Asn1Object externalContent)
  200. {
  201. switch (tagNo)
  202. {
  203. case 1:
  204. return Asn1OctetString.Meta.Instance.CheckedCast(externalContent);
  205. case 2:
  206. return DerBitString.Meta.Instance.CheckedCast(externalContent);
  207. default:
  208. return externalContent;
  209. }
  210. }
  211. private static Asn1Object GetExternalContent(Asn1TaggedObject encoding)
  212. {
  213. int tagClass = encoding.TagClass, tagNo = encoding.TagNo;
  214. if (Asn1Tags.ContextSpecific != tagClass)
  215. throw new ArgumentException("invalid tag: " + Asn1Utilities.GetTagText(tagClass, tagNo), "encoding");
  216. switch (tagNo)
  217. {
  218. case 0:
  219. return encoding.GetExplicitBaseObject().ToAsn1Object();
  220. case 1:
  221. return Asn1OctetString.GetInstance(encoding, false);
  222. case 2:
  223. return DerBitString.GetInstance(encoding, false);
  224. default:
  225. throw new ArgumentException("invalid tag: " + Asn1Utilities.GetTagText(tagClass, tagNo), "encoding");
  226. }
  227. }
  228. private static Asn1Object GetObjFromSequence(Asn1Sequence sequence, int index)
  229. {
  230. if (sequence.Count <= index)
  231. throw new ArgumentException("too few objects in input sequence", "sequence");
  232. return sequence[index].ToAsn1Object();
  233. }
  234. }
  235. }
  236. #pragma warning restore
  237. #endif