AsnEncodedData.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. //
  2. // AsnEncodedData.cs - System.Security.Cryptography.AsnEncodedData
  3. //
  4. // Author:
  5. // Sebastien Pouliot <[email protected]>
  6. //
  7. // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
  8. // Copyright (C) 2004-2005 Novell Inc. (http://www.novell.com)
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. #if NET_2_0
  30. using System.Security.Cryptography.X509Certificates;
  31. using System.Text;
  32. using Mono.Security;
  33. using Mono.Security.Cryptography;
  34. namespace System.Security.Cryptography {
  35. internal enum AsnDecodeStatus {
  36. NotDecoded = -1,
  37. Ok = 0,
  38. BadAsn = 1,
  39. BadTag = 2,
  40. BadLength = 3,
  41. InformationNotAvailable = 4
  42. }
  43. public class AsnEncodedData {
  44. internal Oid _oid;
  45. internal byte[] _raw;
  46. // constructors
  47. protected AsnEncodedData ()
  48. {
  49. }
  50. public AsnEncodedData (string oid, byte[] rawData)
  51. {
  52. _oid = new Oid (oid);
  53. RawData = rawData;
  54. }
  55. public AsnEncodedData (Oid oid, byte[] rawData)
  56. {
  57. Oid = oid;
  58. RawData = rawData;
  59. // yes, here oid == null is legal (by design),
  60. // but no, it would not be legal for an oid string
  61. // see MSDN FDBK11479
  62. }
  63. public AsnEncodedData (AsnEncodedData asnEncodedData)
  64. {
  65. if (asnEncodedData == null)
  66. throw new ArgumentNullException ("asnEncodedData");
  67. Oid = new Oid (asnEncodedData._oid);
  68. RawData = asnEncodedData._raw;
  69. }
  70. public AsnEncodedData (byte[] rawData)
  71. {
  72. RawData = rawData;
  73. }
  74. // properties
  75. public Oid Oid {
  76. get { return _oid; }
  77. set {
  78. if (value == null)
  79. _oid = null;
  80. else
  81. _oid = new Oid (value);
  82. }
  83. }
  84. public byte[] RawData {
  85. get { return _raw; }
  86. set {
  87. if (value == null)
  88. throw new ArgumentNullException ("RawData");
  89. _raw = (byte[])value.Clone ();
  90. }
  91. }
  92. // methods
  93. public virtual void CopyFrom (AsnEncodedData asnEncodedData)
  94. {
  95. if (asnEncodedData == null)
  96. throw new ArgumentNullException ("asnEncodedData");
  97. if (asnEncodedData._oid == null)
  98. Oid = null;
  99. else
  100. Oid = new Oid (asnEncodedData._oid);
  101. RawData = asnEncodedData._raw;
  102. }
  103. public virtual string Format (bool multiLine)
  104. {
  105. if (_raw == null)
  106. return String.Empty;
  107. if (_oid == null)
  108. return Default (multiLine);
  109. return ToString (multiLine);
  110. }
  111. // internal decoding/formatting methods
  112. internal virtual string ToString (bool multiLine)
  113. {
  114. switch (_oid.Value) {
  115. // fx supported objects
  116. case X509BasicConstraintsExtension.oid:
  117. return BasicConstraintsExtension (multiLine);
  118. case X509EnhancedKeyUsageExtension.oid:
  119. return EnhancedKeyUsageExtension (multiLine);
  120. case X509KeyUsageExtension.oid:
  121. return KeyUsageExtension (multiLine);
  122. case X509SubjectKeyIdentifierExtension.oid:
  123. return SubjectKeyIdentifierExtension (multiLine);
  124. // other known objects (i.e. supported structure) -
  125. // but without any corresponding framework class
  126. case Oid.oidSubjectAltName:
  127. return SubjectAltName (multiLine);
  128. case Oid.oidNetscapeCertType:
  129. return NetscapeCertType (multiLine);
  130. default:
  131. return Default (multiLine);
  132. }
  133. }
  134. internal string Default (bool multiLine)
  135. {
  136. StringBuilder sb = new StringBuilder ();
  137. for (int i=0; i < _raw.Length; i++) {
  138. sb.Append (_raw [i].ToString ("x2"));
  139. if (i != _raw.Length - 1)
  140. sb.Append (" ");
  141. }
  142. return sb.ToString ();
  143. }
  144. // Indirectly (undocumented but) supported extensions
  145. internal string BasicConstraintsExtension (bool multiLine)
  146. {
  147. try {
  148. X509BasicConstraintsExtension bc = new X509BasicConstraintsExtension (this, false);
  149. return bc.ToString (multiLine);
  150. }
  151. catch {
  152. return String.Empty;
  153. }
  154. }
  155. internal string EnhancedKeyUsageExtension (bool multiLine)
  156. {
  157. try {
  158. X509EnhancedKeyUsageExtension eku = new X509EnhancedKeyUsageExtension (this, false);
  159. return eku.ToString (multiLine);
  160. }
  161. catch {
  162. return String.Empty;
  163. }
  164. }
  165. internal string KeyUsageExtension (bool multiLine)
  166. {
  167. try {
  168. X509KeyUsageExtension ku = new X509KeyUsageExtension (this, false);
  169. return ku.ToString (multiLine);
  170. }
  171. catch {
  172. return String.Empty;
  173. }
  174. }
  175. internal string SubjectKeyIdentifierExtension (bool multiLine)
  176. {
  177. try {
  178. X509SubjectKeyIdentifierExtension ski = new X509SubjectKeyIdentifierExtension (this, false);
  179. return ski.ToString (multiLine);
  180. }
  181. catch {
  182. return String.Empty;
  183. }
  184. }
  185. // Indirectly (undocumented but) supported extensions
  186. internal string SubjectAltName (bool multiLine)
  187. {
  188. if (_raw.Length < 5)
  189. return "Information Not Available";
  190. try {
  191. ASN1 ex = new ASN1 (_raw);
  192. StringBuilder sb = new StringBuilder ();
  193. for (int i=0; i < ex.Count; i++) {
  194. ASN1 el = ex [i];
  195. string type = null;
  196. string name = null;
  197. switch (el.Tag) {
  198. case 0x81:
  199. type = "RFC822 Name=";
  200. name = Encoding.ASCII.GetString (el.Value);
  201. break;
  202. case 0x82:
  203. type = "DNS Name=";
  204. name = Encoding.ASCII.GetString (el.Value);
  205. break;
  206. default:
  207. type = String.Format ("Unknown ({0})=", el.Tag);
  208. name = CryptoConvert.ToHex (el.Value);
  209. break;
  210. }
  211. sb.Append (type);
  212. sb.Append (name);
  213. if (multiLine) {
  214. sb.Append (Environment.NewLine);
  215. } else if (i < ex.Count - 1) {
  216. sb.Append (", ");
  217. }
  218. }
  219. return sb.ToString ();
  220. }
  221. catch {
  222. return String.Empty;
  223. }
  224. }
  225. internal string NetscapeCertType (bool multiLine)
  226. {
  227. // 4 byte long, BITSTRING (0x03), Value length of 2
  228. if ((_raw.Length < 4) || (_raw [0] != 0x03) || (_raw [1] != 0x02))
  229. return "Information Not Available";
  230. // first value byte is the number of unused bits
  231. int value = (_raw [3] >> _raw [2]) << _raw [2];
  232. StringBuilder sb = new StringBuilder ();
  233. if ((value & 0x80) == 0x80) {
  234. sb.Append ("SSL Client Authentication");
  235. }
  236. if ((value & 0x40) == 0x40) {
  237. if (sb.Length > 0)
  238. sb.Append (", ");
  239. sb.Append ("SSL Server Authentication");
  240. }
  241. if ((value & 0x20) == 0x20) {
  242. if (sb.Length > 0)
  243. sb.Append (", ");
  244. sb.Append ("SMIME");
  245. }
  246. if ((value & 0x10) == 0x10) {
  247. if (sb.Length > 0)
  248. sb.Append (", ");
  249. sb.Append ("Signature"); // a.k.a. Object Signing / Code Signing
  250. }
  251. if ((value & 0x08) == 0x08) {
  252. if (sb.Length > 0)
  253. sb.Append (", ");
  254. sb.Append ("Unknown cert type");
  255. }
  256. if ((value & 0x04) == 0x04) {
  257. if (sb.Length > 0)
  258. sb.Append (", ");
  259. sb.Append ("SSL CA"); // CA == Certificate Authority
  260. }
  261. if ((value & 0x02) == 0x02) {
  262. if (sb.Length > 0)
  263. sb.Append (", ");
  264. sb.Append ("SMIME CA");
  265. }
  266. if ((value & 0x01) == 0x01) {
  267. if (sb.Length > 0)
  268. sb.Append (", ");
  269. sb.Append ("Signature CA");
  270. }
  271. sb.AppendFormat (" ({0})", value.ToString ("x2"));
  272. return sb.ToString ();
  273. }
  274. }
  275. }
  276. #endif