No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Asn1Node.cs 60KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822
  1. //+-------------------------------------------------------------------------------+
  2. //| Copyright (c) 2003 Liping Dai. All rights reserved. |
  3. //| Web: www.lipingshare.com |
  4. //| Email: lipingshare@yahoo.com |
  5. //| |
  6. //| Copyright and Permission Details: |
  7. //| ================================= |
  8. //| Permission is hereby granted, free of charge, to any person obtaining a copy |
  9. //| of this software and associated documentation files (the "Software"), to deal |
  10. //| in the Software without restriction, including without limitation the rights |
  11. //| to use, copy, modify, merge, publish, distribute, and/or sell copies of the |
  12. //| Software, subject to the following conditions: |
  13. //| |
  14. //| 1. Redistributions of source code must retain the above copyright notice, this|
  15. //| list of conditions and the following disclaimer. |
  16. //| |
  17. //| 2. Redistributions in binary form must reproduce the above copyright notice, |
  18. //| this list of conditions and the following disclaimer in the documentation |
  19. //| and/or other materials provided with the distribution. |
  20. //| |
  21. //| THE SOFTWARE PRODUCT IS PROVIDED �AS IS� WITHOUT WARRANTY OF ANY KIND, |
  22. //| EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
  23. //| WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR |
  24. //| A PARTICULAR PURPOSE. |
  25. //+-------------------------------------------------------------------------------+
  26. using System;
  27. using System.IO;
  28. using System.Collections;
  29. using System.Linq;
  30. using System.Text;
  31. using UnityEngine;
  32. namespace LipingShare.LCLib.Asn1Processor
  33. {
  34. /// <summary>
  35. /// Asn1Node, implemented IAsn1Node interface.
  36. /// </summary>
  37. internal class Asn1Node : IAsn1Node
  38. {
  39. // PrivateMembers
  40. private byte tag;
  41. private long dataOffset;
  42. private long dataLength;
  43. private long lengthFieldBytes;
  44. private byte[] data;
  45. private ArrayList childNodeList;
  46. private byte unusedBits;
  47. private long deepness;
  48. private string path = "";
  49. private const int indentStep = 3;
  50. private Asn1Node parentNode;
  51. private bool requireRecalculatePar = true;
  52. private bool isIndefiniteLength = false;
  53. private bool parseEncapsulatedData = true;
  54. /// <summary>
  55. /// Default Asn1Node text line length.
  56. /// </summary>
  57. public const int defaultLineLen = 80;
  58. /// <summary>
  59. /// Minium line length.
  60. /// </summary>
  61. public const int minLineLen = 60;
  62. const int k_EndOfStream = -1;
  63. const int k_InvalidIndeterminateContentLength = -1;
  64. const int k_IndefiniteLengthFooterSize = 2;
  65. private Asn1Node(Asn1Node parentNode, long dataOffset)
  66. {
  67. Init();
  68. deepness = parentNode.Deepness + 1;
  69. this.parentNode = parentNode;
  70. this.dataOffset = dataOffset;
  71. }
  72. private void Init()
  73. {
  74. childNodeList = new ArrayList();
  75. data = null;
  76. dataLength = 0;
  77. lengthFieldBytes = 0;
  78. unusedBits = 0;
  79. tag = Asn1Tag.SEQUENCE | Asn1TagClasses.CONSTRUCTED;
  80. childNodeList.Clear();
  81. deepness = 0;
  82. parentNode = null;
  83. }
  84. private string GetHexPrintingStr(Asn1Node startNode, string baseLine,
  85. string lStr, int lineLen)
  86. {
  87. string nodeStr = "";
  88. string iStr = GetIndentStr(startNode);
  89. string dataStr = Asn1Util.ToHexString(data);
  90. if (dataStr.Length > 0)
  91. {
  92. if (baseLine.Length + dataStr.Length < lineLen)
  93. {
  94. nodeStr += baseLine + "'" + dataStr + "'";
  95. }
  96. else
  97. {
  98. nodeStr += baseLine + FormatLineHexString(
  99. lStr,
  100. iStr.Length,
  101. lineLen,
  102. dataStr
  103. );
  104. }
  105. }
  106. else
  107. {
  108. nodeStr += baseLine;
  109. }
  110. return nodeStr + "\r\n";
  111. }
  112. private string FormatLineString(string lStr, int indent, int lineLen, string msg)
  113. {
  114. string retval = "";
  115. indent += indentStep;
  116. int realLen = lineLen - indent;
  117. int sLen = indent;
  118. int currentp;
  119. for (currentp = 0; currentp < msg.Length; currentp += realLen)
  120. {
  121. if (currentp + realLen > msg.Length)
  122. {
  123. retval += "\r\n" + lStr + Asn1Util.GenStr(sLen, ' ') +
  124. "'" + msg.Substring(currentp, msg.Length - currentp) + "'";
  125. }
  126. else
  127. {
  128. retval += "\r\n" + lStr + Asn1Util.GenStr(sLen, ' ') + "'" +
  129. msg.Substring(currentp, realLen) + "'";
  130. }
  131. }
  132. return retval;
  133. }
  134. private string FormatLineHexString(string lStr, int indent, int lineLen, string msg)
  135. {
  136. string retval = "";
  137. indent += indentStep;
  138. int realLen = lineLen - indent;
  139. int sLen = indent;
  140. int currentp;
  141. for (currentp = 0; currentp < msg.Length; currentp += realLen)
  142. {
  143. if (currentp + realLen > msg.Length)
  144. {
  145. retval += "\r\n" + lStr + Asn1Util.GenStr(sLen, ' ') +
  146. msg.Substring(currentp, msg.Length - currentp);
  147. }
  148. else
  149. {
  150. retval += "\r\n" + lStr + Asn1Util.GenStr(sLen, ' ') +
  151. msg.Substring(currentp, realLen);
  152. }
  153. }
  154. return retval;
  155. }
  156. //PublicMembers
  157. /// <summary>
  158. /// Constructor, initialize all the members.
  159. /// </summary>
  160. public Asn1Node()
  161. {
  162. Init();
  163. dataOffset = 0;
  164. }
  165. /// <summary>
  166. /// Get/Set isIndefiniteLength.
  167. /// </summary>
  168. public bool IsIndefiniteLength
  169. {
  170. get
  171. {
  172. return isIndefiniteLength;
  173. }
  174. set
  175. {
  176. isIndefiniteLength = value;
  177. }
  178. }
  179. /// <summary>
  180. /// Clone a new Asn1Node by current node.
  181. /// </summary>
  182. /// <returns>new node.</returns>
  183. public Asn1Node Clone()
  184. {
  185. MemoryStream ms = new MemoryStream();
  186. this.SaveData(ms);
  187. ms.Position = 0;
  188. Asn1Node node = new Asn1Node();
  189. node.LoadData(ms);
  190. return node;
  191. }
  192. /// <summary>
  193. /// Get/Set tag value.
  194. /// </summary>
  195. public byte Tag
  196. {
  197. get
  198. {
  199. return tag;
  200. }
  201. set
  202. {
  203. tag = value;
  204. }
  205. }
  206. public byte MaskedTag
  207. {
  208. get
  209. {
  210. return (byte)(tag & Asn1Tag.TAG_MASK);
  211. }
  212. }
  213. /// <summary>
  214. /// Load data from byte[].
  215. /// </summary>
  216. /// <param name="byteData">byte[]</param>
  217. /// <returns>true:Succeed; false:failed.</returns>
  218. public bool LoadData(byte[] byteData)
  219. {
  220. bool retval = true;
  221. try
  222. {
  223. MemoryStream ms = new MemoryStream(byteData);
  224. ms.Position = 0;
  225. retval = LoadData(ms);
  226. ms.Close();
  227. }
  228. catch
  229. {
  230. retval = false;
  231. }
  232. return retval;
  233. }
  234. /// <summary>
  235. /// Retrieve all the node count in the node subtree.
  236. /// </summary>
  237. /// <param name="node">starting node.</param>
  238. /// <returns>long integer node count in the node subtree.</returns>
  239. public static long GetDescendantNodeCount(Asn1Node node)
  240. {
  241. long count = 0;
  242. count += node.ChildNodeCount;
  243. for (int i = 0; i < node.ChildNodeCount; i++)
  244. {
  245. count += GetDescendantNodeCount(node.GetChildNode(i));
  246. }
  247. return count;
  248. }
  249. /// <summary>
  250. /// Load data from Stream. Start from current position.
  251. /// This function sets requireRecalculatePar to false then calls InternalLoadData
  252. /// to complish the task.
  253. /// </summary>
  254. /// <param name="xdata">Stream</param>
  255. /// <returns>true:Succeed; false:failed.</returns>
  256. public bool LoadData(Stream xdata)
  257. {
  258. bool retval = false;
  259. try
  260. {
  261. RequireRecalculatePar = false;
  262. retval = InternalLoadData(xdata);
  263. return retval;
  264. }
  265. finally
  266. {
  267. RequireRecalculatePar = true;
  268. RecalculateTreePar();
  269. }
  270. }
  271. /// <summary>
  272. /// Call SaveData and return byte[] as result instead stream.
  273. /// </summary>
  274. /// <returns></returns>
  275. public byte[] GetRawData()
  276. {
  277. MemoryStream ms = new MemoryStream();
  278. SaveData(ms);
  279. byte[] retval = new byte[ms.Length];
  280. ms.Position = 0;
  281. ms.Read(retval, 0, (int)ms.Length);
  282. ms.Close();
  283. return retval;
  284. }
  285. /// <summary>
  286. /// Get if data is empty.
  287. /// </summary>
  288. public bool IsEmptyData
  289. {
  290. get
  291. {
  292. if (data == null) return true;
  293. if (data.Length < 1)
  294. return true;
  295. else
  296. return false;
  297. }
  298. }
  299. /// <summary>
  300. /// Save node data into Stream.
  301. /// </summary>
  302. /// <param name="xdata">Stream.</param>
  303. /// <returns>true:Succeed; false:failed.</returns>
  304. public bool SaveData(Stream xdata)
  305. {
  306. bool retval = true;
  307. long nodeCount = ChildNodeCount;
  308. xdata.WriteByte(tag);
  309. Asn1Util.DERLengthEncode(xdata, (ulong)dataLength);
  310. if ((tag) == Asn1Tag.BIT_STRING)
  311. {
  312. xdata.WriteByte(unusedBits);
  313. }
  314. if (nodeCount == 0)
  315. {
  316. if (data != null)
  317. {
  318. xdata.Write(data, 0, data.Length);
  319. }
  320. }
  321. else
  322. {
  323. Asn1Node tempNode;
  324. int i;
  325. for (i = 0; i < nodeCount; i++)
  326. {
  327. tempNode = GetChildNode(i);
  328. retval = tempNode.SaveData(xdata);
  329. }
  330. }
  331. return retval;
  332. }
  333. /// <summary>
  334. /// Clear data and children list.
  335. /// </summary>
  336. public void ClearAll()
  337. {
  338. data = null;
  339. Asn1Node tempNode;
  340. for (int i = 0; i < childNodeList.Count; i++)
  341. {
  342. tempNode = (Asn1Node)childNodeList[i];
  343. tempNode.ClearAll();
  344. }
  345. childNodeList.Clear();
  346. RecalculateTreePar();
  347. }
  348. /// <summary>
  349. /// Add child node at the end of children list.
  350. /// </summary>
  351. /// <param name="xdata">the node that will be add in.</param>
  352. public void AddChild(Asn1Node xdata)
  353. {
  354. childNodeList.Add(xdata);
  355. RecalculateTreePar();
  356. }
  357. /// <summary>
  358. /// Insert a node in the children list before the pointed index.
  359. /// </summary>
  360. /// <param name="xdata">Asn1Node</param>
  361. /// <param name="index">0 based index.</param>
  362. /// <returns>New node index.</returns>
  363. public int InsertChild(Asn1Node xdata, int index)
  364. {
  365. childNodeList.Insert(index, xdata);
  366. RecalculateTreePar();
  367. return index;
  368. }
  369. /// <summary>
  370. /// Insert a node in the children list before the pointed node.
  371. /// </summary>
  372. /// <param name="xdata">Asn1Node that will be instered in the children list.</param>
  373. /// <param name="indexNode">Index node.</param>
  374. /// <returns>New node index.</returns>
  375. public int InsertChild(Asn1Node xdata, Asn1Node indexNode)
  376. {
  377. int index = childNodeList.IndexOf(indexNode);
  378. childNodeList.Insert(index, xdata);
  379. RecalculateTreePar();
  380. return index;
  381. }
  382. /// <summary>
  383. /// Insert a node in the children list after the pointed node.
  384. /// </summary>
  385. /// <param name="xdata">Asn1Node</param>
  386. /// <param name="indexNode">Index node.</param>
  387. /// <returns>New node index.</returns>
  388. public int InsertChildAfter(Asn1Node xdata, Asn1Node indexNode)
  389. {
  390. int index = childNodeList.IndexOf(indexNode) + 1;
  391. childNodeList.Insert(index, xdata);
  392. RecalculateTreePar();
  393. return index;
  394. }
  395. /// <summary>
  396. /// Insert a node in the children list after the pointed node.
  397. /// </summary>
  398. /// <param name="xdata">Asn1Node that will be instered in the children list.</param>
  399. /// <param name="index">0 based index.</param>
  400. /// <returns>New node index.</returns>
  401. public int InsertChildAfter(Asn1Node xdata, int index)
  402. {
  403. int xindex = index + 1;
  404. childNodeList.Insert(xindex, xdata);
  405. RecalculateTreePar();
  406. return xindex;
  407. }
  408. /// <summary>
  409. /// Remove a child from children node list by index.
  410. /// </summary>
  411. /// <param name="index">0 based index.</param>
  412. /// <returns>The Asn1Node just removed from the list.</returns>
  413. public Asn1Node RemoveChild(int index)
  414. {
  415. Asn1Node retval = null;
  416. if (index < (childNodeList.Count - 1))
  417. {
  418. retval = (Asn1Node)childNodeList[index + 1];
  419. }
  420. childNodeList.RemoveAt(index);
  421. if (retval == null)
  422. {
  423. if (childNodeList.Count > 0)
  424. {
  425. retval = GetLastChild();
  426. }
  427. else
  428. {
  429. retval = this;
  430. }
  431. }
  432. RecalculateTreePar();
  433. return retval;
  434. }
  435. Asn1Node GetLastChild()
  436. {
  437. return (Asn1Node)childNodeList[childNodeList.Count - 1];
  438. }
  439. /// <summary>
  440. /// Remove the child from children node list.
  441. /// </summary>
  442. /// <param name="node">The node needs to be removed.</param>
  443. /// <returns></returns>
  444. public Asn1Node RemoveChild(Asn1Node node)
  445. {
  446. Asn1Node retval = null;
  447. int i = childNodeList.IndexOf(node);
  448. retval = RemoveChild(i);
  449. return retval;
  450. }
  451. /// <summary>
  452. /// Get child node count.
  453. /// </summary>
  454. public long ChildNodeCount
  455. {
  456. get
  457. {
  458. return childNodeList.Count;
  459. }
  460. }
  461. /// <summary>
  462. /// Retrieve child node by index.
  463. /// </summary>
  464. /// <param name="index">0 based index.</param>
  465. /// <returns>0 based index.</returns>
  466. public Asn1Node GetChildNode(int index)
  467. {
  468. Asn1Node retval = null;
  469. if (index < ChildNodeCount)
  470. {
  471. retval = (Asn1Node)childNodeList[index];
  472. }
  473. return retval;
  474. }
  475. /// <summary>
  476. /// Get tag name.
  477. /// </summary>
  478. public string TagName
  479. {
  480. get
  481. {
  482. return Asn1Util.GetTagName(tag);
  483. }
  484. }
  485. /// <summary>
  486. /// Get parent node.
  487. /// </summary>
  488. public Asn1Node ParentNode
  489. {
  490. get
  491. {
  492. return parentNode;
  493. }
  494. }
  495. /// <summary>
  496. /// Get the node and all the descendents text description.
  497. /// </summary>
  498. /// <param name="startNode">starting node.</param>
  499. /// <param name="lineLen">line length.</param>
  500. /// <returns></returns>
  501. public string GetText(Asn1Node startNode, int lineLen)
  502. {
  503. string nodeStr = "";
  504. string baseLine = "";
  505. string dataStr = "";
  506. const string lStr = " | | | ";
  507. string oid, oidName;
  508. switch (tag)
  509. {
  510. case Asn1Tag.BIT_STRING:
  511. baseLine =
  512. String.Format("{0,6}|{1,6}|{2,7}|{3} {4} UnusedBits:{5} : ",
  513. dataOffset,
  514. dataLength,
  515. lengthFieldBytes,
  516. GetIndentStr(startNode),
  517. TagName,
  518. unusedBits
  519. );
  520. dataStr = Asn1Util.ToHexString(data);
  521. if (baseLine.Length + dataStr.Length < lineLen)
  522. {
  523. if (dataStr.Length < 1)
  524. {
  525. nodeStr += baseLine + "\r\n";
  526. }
  527. else
  528. {
  529. nodeStr += baseLine + "'" + dataStr + "'\r\n";
  530. }
  531. }
  532. else
  533. {
  534. nodeStr += baseLine + FormatLineHexString(
  535. lStr,
  536. GetIndentStr(startNode).Length,
  537. lineLen,
  538. dataStr + "\r\n"
  539. );
  540. }
  541. break;
  542. case Asn1Tag.OBJECT_IDENTIFIER:
  543. Oid xoid = new Oid();
  544. oid = xoid.Decode(new MemoryStream(data));
  545. oidName = xoid.GetOidName(oid);
  546. nodeStr += String.Format("{0,6}|{1,6}|{2,7}|{3} {4} : {5} [{6}]\r\n",
  547. dataOffset,
  548. dataLength,
  549. lengthFieldBytes,
  550. GetIndentStr(startNode),
  551. TagName,
  552. oidName,
  553. oid
  554. );
  555. break;
  556. case Asn1Tag.RELATIVE_OID:
  557. RelativeOid xiod = new RelativeOid();
  558. oid = xiod.Decode(new MemoryStream(data));
  559. oidName = "";
  560. nodeStr += String.Format("{0,6}|{1,6}|{2,7}|{3} {4} : {5} [{6}]\r\n",
  561. dataOffset,
  562. dataLength,
  563. lengthFieldBytes,
  564. GetIndentStr(startNode),
  565. TagName,
  566. oidName,
  567. oid
  568. );
  569. break;
  570. case Asn1Tag.PRINTABLE_STRING:
  571. case Asn1Tag.IA5_STRING:
  572. case Asn1Tag.UNIVERSAL_STRING:
  573. case Asn1Tag.VISIBLE_STRING:
  574. case Asn1Tag.NUMERIC_STRING:
  575. case Asn1Tag.UTC_TIME:
  576. case Asn1Tag.UTF8_STRING:
  577. case Asn1Tag.BMPSTRING:
  578. case Asn1Tag.GENERAL_STRING:
  579. case Asn1Tag.GENERALIZED_TIME:
  580. baseLine =
  581. String.Format("{0,6}|{1,6}|{2,7}|{3} {4} : ",
  582. dataOffset,
  583. dataLength,
  584. lengthFieldBytes,
  585. GetIndentStr(startNode),
  586. TagName
  587. );
  588. if (tag == Asn1Tag.UTF8_STRING)
  589. {
  590. UTF8Encoding unicode = new UTF8Encoding();
  591. dataStr = unicode.GetString(data);
  592. }
  593. else
  594. {
  595. dataStr = Asn1Util.BytesToString(data);
  596. }
  597. if (baseLine.Length + dataStr.Length < lineLen)
  598. {
  599. nodeStr += baseLine + "'" + dataStr + "'\r\n";
  600. }
  601. else
  602. {
  603. nodeStr += baseLine + FormatLineString(
  604. lStr,
  605. GetIndentStr(startNode).Length,
  606. lineLen,
  607. dataStr) + "\r\n";
  608. }
  609. break;
  610. case Asn1Tag.INTEGER:
  611. if (data != null && dataLength < 8)
  612. {
  613. nodeStr += String.Format("{0,6}|{1,6}|{2,7}|{3} {4} : {5}\r\n",
  614. dataOffset,
  615. dataLength,
  616. lengthFieldBytes,
  617. GetIndentStr(startNode),
  618. TagName,
  619. Asn1Util.BytesToLong(data).ToString()
  620. );
  621. }
  622. else
  623. {
  624. baseLine =
  625. String.Format("{0,6}|{1,6}|{2,7}|{3} {4} : ",
  626. dataOffset,
  627. dataLength,
  628. lengthFieldBytes,
  629. GetIndentStr(startNode),
  630. TagName
  631. );
  632. nodeStr += GetHexPrintingStr(startNode, baseLine, lStr, lineLen);
  633. }
  634. break;
  635. default:
  636. if ((tag & Asn1Tag.TAG_MASK) == 6) // Visible string for certificate
  637. {
  638. baseLine =
  639. String.Format("{0,6}|{1,6}|{2,7}|{3} {4} : ",
  640. dataOffset,
  641. dataLength,
  642. lengthFieldBytes,
  643. GetIndentStr(startNode),
  644. TagName
  645. );
  646. dataStr = Asn1Util.BytesToString(data);
  647. if (baseLine.Length + dataStr.Length < lineLen)
  648. {
  649. nodeStr += baseLine + "'" + dataStr + "'\r\n";
  650. }
  651. else
  652. {
  653. nodeStr += baseLine + FormatLineString(
  654. lStr,
  655. GetIndentStr(startNode).Length,
  656. lineLen,
  657. dataStr) + "\r\n";
  658. }
  659. }
  660. else
  661. {
  662. baseLine =
  663. String.Format("{0,6}|{1,6}|{2,7}|{3} {4} : ",
  664. dataOffset,
  665. dataLength,
  666. lengthFieldBytes,
  667. GetIndentStr(startNode),
  668. TagName
  669. );
  670. nodeStr += GetHexPrintingStr(startNode, baseLine, lStr, lineLen);
  671. }
  672. break;
  673. };
  674. if (childNodeList.Count >= 0)
  675. {
  676. nodeStr += GetListStr(startNode, lineLen);
  677. }
  678. return nodeStr;
  679. }
  680. /// <summary>
  681. /// Get the path string of the node.
  682. /// </summary>
  683. public string Path
  684. {
  685. get
  686. {
  687. return path;
  688. }
  689. }
  690. /// <summary>
  691. /// Retrieve the node description.
  692. /// </summary>
  693. /// <param name="pureHexMode">true:Return hex string only;
  694. /// false:Convert to more readable string depending on the node tag.</param>
  695. /// <returns>string</returns>
  696. public string GetDataStr(bool pureHexMode)
  697. {
  698. const int lineLen = 32;
  699. string dataStr = "";
  700. if (pureHexMode)
  701. {
  702. dataStr = Asn1Util.FormatString(Asn1Util.ToHexString(data), lineLen, 2);
  703. }
  704. else
  705. {
  706. switch (tag)
  707. {
  708. case Asn1Tag.BIT_STRING:
  709. dataStr = Asn1Util.FormatString(Asn1Util.ToHexString(data), lineLen, 2);
  710. break;
  711. case Asn1Tag.OBJECT_IDENTIFIER:
  712. Oid xoid = new Oid();
  713. dataStr = xoid.Decode(new MemoryStream(data));
  714. break;
  715. case Asn1Tag.RELATIVE_OID:
  716. RelativeOid roid = new RelativeOid();
  717. dataStr = roid.Decode(new MemoryStream(data));
  718. break;
  719. case Asn1Tag.PRINTABLE_STRING:
  720. case Asn1Tag.IA5_STRING:
  721. case Asn1Tag.UNIVERSAL_STRING:
  722. case Asn1Tag.VISIBLE_STRING:
  723. case Asn1Tag.NUMERIC_STRING:
  724. case Asn1Tag.UTC_TIME:
  725. case Asn1Tag.BMPSTRING:
  726. case Asn1Tag.GENERAL_STRING:
  727. case Asn1Tag.GENERALIZED_TIME:
  728. dataStr = Asn1Util.BytesToString(data);
  729. break;
  730. case Asn1Tag.UTF8_STRING:
  731. UTF8Encoding utf8 = new UTF8Encoding();
  732. dataStr = utf8.GetString(data);
  733. break;
  734. case Asn1Tag.INTEGER:
  735. dataStr = Asn1Util.FormatString(Asn1Util.ToHexString(data), lineLen, 2);
  736. break;
  737. default:
  738. if ((tag & Asn1Tag.TAG_MASK) == 6) // Visible string for certificate
  739. {
  740. dataStr = Asn1Util.BytesToString(data);
  741. }
  742. else
  743. {
  744. dataStr = Asn1Util.FormatString(Asn1Util.ToHexString(data), lineLen, 2);
  745. }
  746. break;
  747. };
  748. }
  749. return dataStr;
  750. }
  751. /// <summary>
  752. /// Get node label string.
  753. /// </summary>
  754. /// <param name="mask">
  755. /// <code>
  756. /// SHOW_OFFSET
  757. /// SHOW_DATA
  758. /// USE_HEX_OFFSET
  759. /// SHOW_TAG_NUMBER
  760. /// SHOW_PATH</code>
  761. /// </param>
  762. /// <returns>string</returns>
  763. public string GetLabel(uint mask)
  764. {
  765. string nodeStr = "";
  766. string dataStr = "";
  767. string offsetStr = "";
  768. if ((mask & TagTextMask.USE_HEX_OFFSET) != 0)
  769. {
  770. if ((mask & TagTextMask.SHOW_TAG_NUMBER) != 0)
  771. offsetStr = String.Format("(0x{0:X2},0x{1:X6},0x{2:X4})", tag, dataOffset, dataLength);
  772. else
  773. offsetStr = String.Format("(0x{0:X6},0x{1:X4})", dataOffset, dataLength);
  774. }
  775. else
  776. {
  777. if ((mask & TagTextMask.SHOW_TAG_NUMBER) != 0)
  778. offsetStr = String.Format("({0},{1},{2})", tag, dataOffset, dataLength);
  779. else
  780. offsetStr = String.Format("({0},{1})", dataOffset, dataLength);
  781. }
  782. string oid, oidName;
  783. switch (tag)
  784. {
  785. case Asn1Tag.BIT_STRING:
  786. if ((mask & TagTextMask.SHOW_OFFSET) != 0)
  787. {
  788. nodeStr += offsetStr;
  789. }
  790. nodeStr += " " + TagName + " UnusedBits: " + unusedBits.ToString();
  791. if ((mask & TagTextMask.SHOW_DATA) != 0)
  792. {
  793. dataStr = Asn1Util.ToHexString(data);
  794. nodeStr += ((dataStr.Length > 0) ? " : '" + dataStr + "'" : "");
  795. }
  796. break;
  797. case Asn1Tag.OBJECT_IDENTIFIER:
  798. Oid xoid = new Oid();
  799. oid = xoid.Decode(data);
  800. oidName = xoid.GetOidName(oid);
  801. if ((mask & TagTextMask.SHOW_OFFSET) != 0)
  802. {
  803. nodeStr += offsetStr;
  804. }
  805. nodeStr += " " + TagName;
  806. nodeStr += " : " + oidName;
  807. if ((mask & TagTextMask.SHOW_DATA) != 0)
  808. {
  809. nodeStr += ((oid.Length > 0) ? " : '" + oid + "'" : "");
  810. }
  811. break;
  812. case Asn1Tag.RELATIVE_OID:
  813. RelativeOid roid = new RelativeOid();
  814. oid = roid.Decode(data);
  815. oidName = "";
  816. if ((mask & TagTextMask.SHOW_OFFSET) != 0)
  817. {
  818. nodeStr += offsetStr;
  819. }
  820. nodeStr += " " + TagName;
  821. nodeStr += " : " + oidName;
  822. if ((mask & TagTextMask.SHOW_DATA) != 0)
  823. {
  824. nodeStr += ((oid.Length > 0) ? " : '" + oid + "'" : "");
  825. }
  826. break;
  827. case Asn1Tag.PRINTABLE_STRING:
  828. case Asn1Tag.IA5_STRING:
  829. case Asn1Tag.UNIVERSAL_STRING:
  830. case Asn1Tag.VISIBLE_STRING:
  831. case Asn1Tag.NUMERIC_STRING:
  832. case Asn1Tag.UTC_TIME:
  833. case Asn1Tag.UTF8_STRING:
  834. case Asn1Tag.BMPSTRING:
  835. case Asn1Tag.GENERAL_STRING:
  836. case Asn1Tag.GENERALIZED_TIME:
  837. if ((mask & TagTextMask.SHOW_OFFSET) != 0)
  838. {
  839. nodeStr += offsetStr;
  840. }
  841. nodeStr += " " + TagName;
  842. if ((mask & TagTextMask.SHOW_DATA) != 0)
  843. {
  844. if (tag == Asn1Tag.UTF8_STRING)
  845. {
  846. UTF8Encoding unicode = new UTF8Encoding();
  847. dataStr = unicode.GetString(data);
  848. }
  849. else
  850. {
  851. dataStr = Asn1Util.BytesToString(data);
  852. }
  853. nodeStr += ((dataStr.Length > 0) ? " : '" + dataStr + "'" : "");
  854. }
  855. break;
  856. case Asn1Tag.INTEGER:
  857. if ((mask & TagTextMask.SHOW_OFFSET) != 0)
  858. {
  859. nodeStr += offsetStr;
  860. }
  861. nodeStr += " " + TagName;
  862. if ((mask & TagTextMask.SHOW_DATA) != 0)
  863. {
  864. if (data != null && dataLength < 8)
  865. {
  866. dataStr = Asn1Util.BytesToLong(data).ToString();
  867. }
  868. else
  869. {
  870. dataStr = Asn1Util.ToHexString(data);
  871. }
  872. nodeStr += ((dataStr.Length > 0) ? " : '" + dataStr + "'" : "");
  873. }
  874. break;
  875. default:
  876. if ((mask & TagTextMask.SHOW_OFFSET) != 0)
  877. {
  878. nodeStr += offsetStr;
  879. }
  880. nodeStr += " " + TagName;
  881. if ((mask & TagTextMask.SHOW_DATA) != 0)
  882. {
  883. if ((tag & Asn1Tag.TAG_MASK) == 6) // Visible string for certificate
  884. {
  885. dataStr = Asn1Util.BytesToString(data);
  886. }
  887. else
  888. {
  889. dataStr = Asn1Util.ToHexString(data);
  890. }
  891. nodeStr += ((dataStr.Length > 0) ? " : '" + dataStr + "'" : "");
  892. }
  893. break;
  894. };
  895. if ((mask & TagTextMask.SHOW_PATH) != 0)
  896. {
  897. nodeStr = "(" + path + ") " + nodeStr;
  898. }
  899. return nodeStr;
  900. }
  901. /// <summary>
  902. /// Get data length. Not included the unused bits byte for BITSTRING.
  903. /// </summary>
  904. public long DataLength
  905. {
  906. get
  907. {
  908. return dataLength;
  909. }
  910. }
  911. /// <summary>
  912. /// Get the length field bytes.
  913. /// </summary>
  914. public long LengthFieldBytes
  915. {
  916. get
  917. {
  918. return lengthFieldBytes;
  919. }
  920. }
  921. /// <summary>
  922. /// Get/Set node data by byte[], the data length field content and all the
  923. /// node in the parent chain will be adjusted.
  924. /// <br></br>
  925. /// It return all the child data for constructed node.
  926. /// </summary>
  927. public byte[] Data
  928. {
  929. get
  930. {
  931. MemoryStream xdata = new MemoryStream();
  932. long nodeCount = ChildNodeCount;
  933. if (nodeCount == 0)
  934. {
  935. if (data != null)
  936. {
  937. xdata.Write(data, 0, data.Length);
  938. }
  939. }
  940. else
  941. {
  942. Asn1Node tempNode;
  943. for (int i = 0; i < nodeCount; i++)
  944. {
  945. tempNode = GetChildNode(i);
  946. tempNode.SaveData(xdata);
  947. }
  948. }
  949. byte[] tmpData = new byte[xdata.Length];
  950. xdata.Position = 0;
  951. xdata.Read(tmpData, 0, (int)xdata.Length);
  952. xdata.Close();
  953. return tmpData;
  954. }
  955. set
  956. {
  957. SetData(value);
  958. }
  959. }
  960. /// <summary>
  961. /// Get the deepness of the node.
  962. /// </summary>
  963. public long Deepness
  964. {
  965. get
  966. {
  967. return deepness;
  968. }
  969. }
  970. /// <summary>
  971. /// Get data offset.
  972. /// </summary>
  973. public long DataOffset
  974. {
  975. get
  976. {
  977. return dataOffset;
  978. }
  979. }
  980. /// <summary>
  981. /// Get unused bits for BITSTRING.
  982. /// </summary>
  983. public byte UnusedBits
  984. {
  985. get
  986. {
  987. return unusedBits;
  988. }
  989. set
  990. {
  991. unusedBits = value;
  992. }
  993. }
  994. /// <summary>
  995. /// Get descendant node by node path.
  996. /// </summary>
  997. /// <param name="nodePath">relative node path that refer to current node.</param>
  998. /// <returns></returns>
  999. public Asn1Node GetDescendantNodeByPath(string nodePath)
  1000. {
  1001. Asn1Node retval = this;
  1002. if (nodePath == null) return retval;
  1003. nodePath = nodePath.TrimEnd().TrimStart();
  1004. if (nodePath.Length < 1) return retval;
  1005. string[] route = nodePath.Split('/');
  1006. try
  1007. {
  1008. for (int i = 1; i < route.Length; i++)
  1009. {
  1010. retval = retval.GetChildNode(Convert.ToInt32(route[i]));
  1011. }
  1012. }
  1013. catch
  1014. {
  1015. retval = null;
  1016. }
  1017. return retval;
  1018. }
  1019. /// <summary>
  1020. /// Get node by OID.
  1021. /// </summary>
  1022. /// <param name="oid">OID.</param>
  1023. /// <param name="startNode">Starting node.</param>
  1024. /// <returns>Null or Asn1Node.</returns>
  1025. static public Asn1Node GetDecendantNodeByOid(string oid, Asn1Node startNode)
  1026. {
  1027. Asn1Node retval = null;
  1028. Oid xoid = new Oid();
  1029. for (int i = 0; i < startNode.ChildNodeCount; i++)
  1030. {
  1031. Asn1Node childNode = startNode.GetChildNode(i);
  1032. int tmpTag = childNode.tag & Asn1Tag.TAG_MASK;
  1033. if (tmpTag == Asn1Tag.OBJECT_IDENTIFIER)
  1034. {
  1035. if (oid == xoid.Decode(childNode.Data))
  1036. {
  1037. retval = childNode;
  1038. break;
  1039. }
  1040. }
  1041. retval = GetDecendantNodeByOid(oid, childNode);
  1042. if (retval != null) break;
  1043. }
  1044. return retval;
  1045. }
  1046. /// <summary>
  1047. /// Constant of tag field length.
  1048. /// </summary>
  1049. public const int TagLength = 1;
  1050. /// <summary>
  1051. /// Constant of unused bits field length.
  1052. /// </summary>
  1053. public const int BitStringUnusedFiledLength = 1;
  1054. /// <summary>
  1055. /// Tag text generation mask definition.
  1056. /// </summary>
  1057. public class TagTextMask
  1058. {
  1059. /// <summary>
  1060. /// Show offset.
  1061. /// </summary>
  1062. public const uint SHOW_OFFSET = 0x01;
  1063. /// <summary>
  1064. /// Show decoded data.
  1065. /// </summary>
  1066. public const uint SHOW_DATA = 0x02;
  1067. /// <summary>
  1068. /// Show offset in hex format.
  1069. /// </summary>
  1070. public const uint USE_HEX_OFFSET = 0x04;
  1071. /// <summary>
  1072. /// Show tag.
  1073. /// </summary>
  1074. public const uint SHOW_TAG_NUMBER = 0x08;
  1075. /// <summary>
  1076. /// Show node path.
  1077. /// </summary>
  1078. public const uint SHOW_PATH = 0x10;
  1079. }
  1080. /// <summary>
  1081. /// Set/Get requireRecalculatePar. RecalculateTreePar function will not do anything
  1082. /// if it is set to false.
  1083. /// </summary>
  1084. protected bool RequireRecalculatePar
  1085. {
  1086. get
  1087. {
  1088. return requireRecalculatePar;
  1089. }
  1090. set
  1091. {
  1092. requireRecalculatePar = value;
  1093. }
  1094. }
  1095. //ProtectedMembers
  1096. /// <summary>
  1097. /// Find root node and recalculate entire tree length field,
  1098. /// path, offset and deepness.
  1099. /// </summary>
  1100. protected void RecalculateTreePar()
  1101. {
  1102. if (!requireRecalculatePar) return;
  1103. Asn1Node rootNode;
  1104. for (rootNode = this; rootNode.ParentNode != null;)
  1105. {
  1106. rootNode = rootNode.ParentNode;
  1107. }
  1108. ResetBranchDataLength(rootNode);
  1109. rootNode.dataOffset = 0;
  1110. rootNode.deepness = 0;
  1111. long subOffset = rootNode.dataOffset + TagLength + rootNode.lengthFieldBytes;
  1112. ResetChildNodePar(rootNode, subOffset);
  1113. }
  1114. /// <summary>
  1115. /// Recursively set all the node data length.
  1116. /// </summary>
  1117. /// <param name="node"></param>
  1118. /// <returns>node data length.</returns>
  1119. protected static long ResetBranchDataLength(Asn1Node node)
  1120. {
  1121. long retval = 0;
  1122. long childDataLength = 0;
  1123. if (node.ChildNodeCount < 1)
  1124. {
  1125. if (node.data != null)
  1126. childDataLength += node.data.Length;
  1127. }
  1128. else
  1129. {
  1130. for (int i = 0; i < node.ChildNodeCount; i++)
  1131. {
  1132. childDataLength += ResetBranchDataLength(node.GetChildNode(i));
  1133. }
  1134. }
  1135. node.dataLength = childDataLength;
  1136. if (node.tag == Asn1Tag.BIT_STRING)
  1137. node.dataLength += BitStringUnusedFiledLength;
  1138. ResetDataLengthFieldWidth(node);
  1139. retval = node.dataLength + TagLength + node.lengthFieldBytes;
  1140. return retval;
  1141. }
  1142. /// <summary>
  1143. /// Encode the node data length field and set lengthFieldBytes and dataLength.
  1144. /// </summary>
  1145. /// <param name="node">The node needs to be reset.</param>
  1146. protected static void ResetDataLengthFieldWidth(Asn1Node node)
  1147. {
  1148. MemoryStream tempStream = new MemoryStream();
  1149. Asn1Util.DERLengthEncode(tempStream, (ulong)node.dataLength);
  1150. node.lengthFieldBytes = tempStream.Length;
  1151. tempStream.Close();
  1152. }
  1153. /// <summary>
  1154. /// Recursively set all the child parameters, except dataLength.
  1155. /// dataLength is set by ResetBranchDataLength.
  1156. /// </summary>
  1157. /// <param name="xNode">Starting node.</param>
  1158. /// <param name="subOffset">Starting node offset.</param>
  1159. protected void ResetChildNodePar(Asn1Node xNode, long subOffset)
  1160. {
  1161. int i;
  1162. if (xNode.tag == Asn1Tag.BIT_STRING)
  1163. {
  1164. subOffset++;
  1165. }
  1166. Asn1Node tempNode;
  1167. for (i = 0; i < xNode.ChildNodeCount; i++)
  1168. {
  1169. tempNode = xNode.GetChildNode(i);
  1170. tempNode.parentNode = xNode;
  1171. tempNode.dataOffset = subOffset;
  1172. tempNode.deepness = xNode.deepness + 1;
  1173. tempNode.path = xNode.path + '/' + i.ToString();
  1174. subOffset += TagLength + tempNode.lengthFieldBytes;
  1175. ResetChildNodePar(tempNode, subOffset);
  1176. subOffset += tempNode.dataLength;
  1177. }
  1178. }
  1179. /// <summary>
  1180. /// Generate all the child text from childNodeList.
  1181. /// </summary>
  1182. /// <param name="startNode">Starting node.</param>
  1183. /// <param name="lineLen">Line length.</param>
  1184. /// <returns>Text string.</returns>
  1185. protected string GetListStr(Asn1Node startNode, int lineLen)
  1186. {
  1187. string nodeStr = "";
  1188. int i;
  1189. Asn1Node tempNode;
  1190. for (i = 0; i < childNodeList.Count; i++)
  1191. {
  1192. tempNode = (Asn1Node)childNodeList[i];
  1193. nodeStr += tempNode.GetText(startNode, lineLen);
  1194. }
  1195. return nodeStr;
  1196. }
  1197. /// <summary>
  1198. /// Generate the node indent string.
  1199. /// </summary>
  1200. /// <param name="startNode">The node.</param>
  1201. /// <returns>Text string.</returns>
  1202. protected string GetIndentStr(Asn1Node startNode)
  1203. {
  1204. string retval = "";
  1205. long startLen = 0;
  1206. if (startNode != null)
  1207. {
  1208. startLen = startNode.Deepness;
  1209. }
  1210. for (long i = 0; i < deepness - startLen; i++)
  1211. {
  1212. retval += " ";
  1213. }
  1214. return retval;
  1215. }
  1216. /// <summary>
  1217. /// Decode ASN.1 encoded node Stream data.
  1218. /// </summary>
  1219. /// <param name="xdata">Stream data.</param>
  1220. /// <returns>true:Succeed, false:Failed.</returns>
  1221. protected bool GeneralDecode(Stream xdata)
  1222. {
  1223. long nodeMaxLen = xdata.Length - xdata.Position;
  1224. tag = (byte)xdata.ReadByte();
  1225. long start = xdata.Position;
  1226. dataLength = Asn1Util.DerLengthDecode(xdata, ref isIndefiniteLength);
  1227. if (AreTagsOk())
  1228. {
  1229. if (isIndefiniteLength)
  1230. {
  1231. return GeneralDecodeIndefiniteLength(xdata, nodeMaxLen - k_IndefiniteLengthFooterSize);
  1232. }
  1233. else
  1234. {
  1235. return GeneralDecodeKnownLengthWithChecks(xdata, start, nodeMaxLen);
  1236. }
  1237. }
  1238. else
  1239. {
  1240. return false;
  1241. }
  1242. }
  1243. private bool AreTagsOk()
  1244. {
  1245. if (ParentNode == null || ((ParentNode.tag & Asn1TagClasses.CONSTRUCTED) == 0))
  1246. {
  1247. if ((tag & Asn1Tag.TAG_MASK) <= 0 || (tag & Asn1Tag.TAG_MASK) > 0x1E)
  1248. {
  1249. return false;
  1250. }
  1251. }
  1252. return true;
  1253. }
  1254. private bool GeneralDecodeKnownLengthWithChecks(Stream xdata, long start, long nodeMaxLen)
  1255. {
  1256. if (IsGeneralStreamLengthOk(xdata, start, nodeMaxLen))
  1257. {
  1258. return GeneralDecodeKnownLength(xdata);
  1259. }
  1260. return false;
  1261. }
  1262. private bool IsGeneralStreamLengthOk(Stream xdata, long start, long nodeMaxLen)
  1263. {
  1264. if (dataLength >= 0)
  1265. {
  1266. lengthFieldBytes = xdata.Position - start;
  1267. if (nodeMaxLen >= (dataLength + TagLength + lengthFieldBytes))
  1268. {
  1269. return true;
  1270. }
  1271. }
  1272. return false;
  1273. }
  1274. private bool GeneralDecodeKnownLength(Stream xdata)
  1275. {
  1276. if (tag == Asn1Tag.BIT_STRING)
  1277. {
  1278. // First byte of BIT_STRING is unused bits.
  1279. // BIT_STRING data does not include this byte.
  1280. // Fixed by Gustaf Bj�rklund.
  1281. if (dataLength < 1)
  1282. {
  1283. return false;
  1284. }
  1285. unusedBits = (byte)xdata.ReadByte();
  1286. ReadStreamDataDefiniteLength(xdata, (int)(dataLength - 1));
  1287. }
  1288. else
  1289. {
  1290. ReadStreamDataDefiniteLength(xdata, (int)(dataLength));
  1291. }
  1292. return true;
  1293. }
  1294. private void ReadStreamDataDefiniteLength(Stream xdata, int length)
  1295. {
  1296. data = new byte[length];
  1297. xdata.Read(data, 0, (int)(length));
  1298. }
  1299. private bool GeneralDecodeIndefiniteLength(Stream xdata, long nodeMaxLen)
  1300. {
  1301. if (tag == Asn1Tag.BIT_STRING)
  1302. {
  1303. unusedBits = (byte)xdata.ReadByte();
  1304. nodeMaxLen--;
  1305. }
  1306. return ReadStreamDataIndefiniteLength(xdata, nodeMaxLen);
  1307. }
  1308. bool ReadStreamDataIndefiniteLength(Stream xdata, long nodeMaxLen)
  1309. {
  1310. var streamPosition = xdata.Position;
  1311. long contentLength = MeasureContentLength(xdata);
  1312. if (contentLength != k_InvalidIndeterminateContentLength && contentLength <= nodeMaxLen)
  1313. {
  1314. ReadMeasuredLengthDataFromStart(xdata, streamPosition, contentLength);
  1315. return true;
  1316. }
  1317. else
  1318. {
  1319. return false;
  1320. }
  1321. }
  1322. long MeasureContentLength(Stream xdata)
  1323. {
  1324. long contentLength = 0;
  1325. bool firstEocByteFound = false;
  1326. bool foundEoc = false;
  1327. while (!foundEoc)
  1328. {
  1329. var currentByte = xdata.ReadByte();
  1330. if (currentByte == k_EndOfStream)
  1331. {
  1332. foundEoc = true;
  1333. contentLength = k_InvalidIndeterminateContentLength;
  1334. }
  1335. else if (currentByte == Asn1Tag.TAG_END_OF_CONTENTS)
  1336. {
  1337. if (firstEocByteFound)
  1338. {
  1339. foundEoc = true;
  1340. }
  1341. else
  1342. {
  1343. firstEocByteFound = true;
  1344. }
  1345. }
  1346. else
  1347. {
  1348. if (firstEocByteFound)
  1349. {
  1350. firstEocByteFound = false;
  1351. contentLength++;
  1352. }
  1353. contentLength++;
  1354. }
  1355. }
  1356. return contentLength;
  1357. }
  1358. void ReadMeasuredLengthDataFromStart(Stream xdata, long startPosition, long length)
  1359. {
  1360. xdata.Seek(startPosition, SeekOrigin.Begin);
  1361. data = new byte[length];
  1362. xdata.Read(data, 0, (int)(length));
  1363. }
  1364. /// <summary>
  1365. /// Decode ASN.1 encoded complex data type Stream data.
  1366. /// </summary>
  1367. /// <param name="xdata">Stream data.</param>
  1368. /// <returns>true:Succeed, false:Failed.</returns>
  1369. protected bool ListDecode(Stream xdata)
  1370. {
  1371. bool retval = false;
  1372. long originalPosition = xdata.Position;
  1373. try
  1374. {
  1375. tag = (byte)xdata.ReadByte();
  1376. long start = xdata.Position;
  1377. dataLength = Asn1Util.DerLengthDecode(xdata, ref isIndefiniteLength);
  1378. long childNodeMaxLen = xdata.Length - xdata.Position;
  1379. if (isIndefiniteLength)
  1380. {
  1381. retval = ListDecodeIndefiniteLength(xdata, start, childNodeMaxLen - k_IndefiniteLengthFooterSize);
  1382. }
  1383. else
  1384. {
  1385. retval = ListDecodeKnownLengthWithChecks(xdata, start, childNodeMaxLen);
  1386. }
  1387. }
  1388. finally
  1389. {
  1390. if (!retval)
  1391. {
  1392. xdata.Position = originalPosition;
  1393. ClearAll();
  1394. }
  1395. }
  1396. return retval;
  1397. }
  1398. private bool ListDecodeKnownLengthWithChecks(Stream xdata, long start, long childNodeMaxLen)
  1399. {
  1400. if (IsListStreamLengthOk(xdata, childNodeMaxLen))
  1401. {
  1402. return ListDecodeKnownLength(xdata, start);
  1403. }
  1404. return false;
  1405. }
  1406. private bool IsListStreamLengthOk(Stream xdata, long childNodeMaxLen)
  1407. {
  1408. return (dataLength >= 0 && childNodeMaxLen >= dataLength);
  1409. }
  1410. private bool ListDecodeKnownLength(Stream xdata, long start)
  1411. {
  1412. long offset = CalculateListEncodeFieldBytesAndOffset(xdata, start);
  1413. HandleBitStringTag(xdata, ref offset);
  1414. if (dataLength > 0)
  1415. {
  1416. return ListDecodeKnownLengthInternal(xdata, offset);
  1417. }
  1418. return false;
  1419. }
  1420. private long CalculateListEncodeFieldBytesAndOffset(Stream xdata, long start)
  1421. {
  1422. lengthFieldBytes = xdata.Position - start;
  1423. return dataOffset + TagLength + lengthFieldBytes;
  1424. }
  1425. bool HandleBitStringTag(Stream xdata, ref long offset)
  1426. {
  1427. if (tag == Asn1Tag.BIT_STRING)
  1428. {
  1429. // First byte of BIT_STRING is unused bits.
  1430. // BIT_STRING data does not include this byte.
  1431. unusedBits = (byte)xdata.ReadByte();
  1432. dataLength--;
  1433. offset++;
  1434. return true;
  1435. }
  1436. return false;
  1437. }
  1438. private bool ListDecodeKnownLengthInternal(Stream xdata, long offset)
  1439. {
  1440. Stream secData = CreateAndPrepareListDecodeMemoryStreamKnownLength(xdata);
  1441. return ListDecodeChildNodesWithKnownLength(secData, offset);
  1442. }
  1443. private Stream CreateAndPrepareListDecodeMemoryStreamKnownLength(Stream xdata)
  1444. {
  1445. Stream secData = new MemoryStream((int)dataLength);
  1446. byte[] secByte = new byte[dataLength];
  1447. xdata.Read(secByte, 0, (int)(dataLength));
  1448. if (tag == Asn1Tag.BIT_STRING)
  1449. {
  1450. dataLength++;
  1451. }
  1452. secData.Write(secByte, 0, secByte.Length);
  1453. secData.Position = 0;
  1454. return secData;
  1455. }
  1456. private bool ListDecodeChildNodesWithKnownLength(Stream secData, long offset)
  1457. {
  1458. while (secData.Position < secData.Length)
  1459. {
  1460. if (!CreateAndAddChildNode(secData, ref offset))
  1461. {
  1462. return false;
  1463. }
  1464. }
  1465. return true;
  1466. }
  1467. private bool CreateAndAddChildNode(Stream secData, ref long offset)
  1468. {
  1469. var node = new Asn1Node(this, offset);
  1470. node.parseEncapsulatedData = this.parseEncapsulatedData;
  1471. long start = secData.Position;
  1472. if (!node.InternalLoadData(secData))
  1473. {
  1474. return false;
  1475. }
  1476. AddChild(node);
  1477. offset += secData.Position - start;
  1478. return true;
  1479. }
  1480. private bool ListDecodeIndefiniteLength(Stream xdata, long start, long childNodeMaxLen)
  1481. {
  1482. long offset = CalculateListEncodeFieldBytesAndOffset(xdata, start);
  1483. if (HandleBitStringTag(xdata, ref offset))
  1484. {
  1485. childNodeMaxLen--;
  1486. }
  1487. return ListDecodeIndefiniteLengthInternal(xdata, offset, childNodeMaxLen);
  1488. }
  1489. bool ListDecodeIndefiniteLengthInternal(Stream xdata, long offset, long childNodeMaxLen)
  1490. {
  1491. bool doneReading = false;
  1492. while (!doneReading)
  1493. {
  1494. var oldOffset = offset;
  1495. doneReading = ReadNextChildNodeOrEndFooterOfIndefiniteListClearIfInvalid(xdata, ref offset, childNodeMaxLen);
  1496. childNodeMaxLen -= (offset - oldOffset);
  1497. }
  1498. return ChildNodeCount > 0;
  1499. }
  1500. bool ReadNextChildNodeOrEndFooterOfIndefiniteListClearIfInvalid(Stream xdata, ref long offset, long childNodeMaxLen)
  1501. {
  1502. bool doneReading;
  1503. var byteChecks = DetectEndOfIndefiniteListContents(xdata);
  1504. if (byteChecks == Asn1EndOfIndefiniteLengthNodeType.NotEnd)
  1505. {
  1506. doneReading = !ReadNextChildNodeOfIndefiniteListClearIfInvalid(xdata, ref offset, childNodeMaxLen);
  1507. }
  1508. else
  1509. {
  1510. if (byteChecks == Asn1EndOfIndefiniteLengthNodeType.EndOfStream && ChildNodeCount > 0)
  1511. {
  1512. //DEVELOPERS' NOTE:
  1513. //End of Stream hit parsing an Indeterminate Length List Node.
  1514. //This Indeterminate Length List Node is a false flag that just happens to have initial bytes matching the pattern of such a node.
  1515. ClearAll();
  1516. }
  1517. doneReading = true;
  1518. }
  1519. return doneReading;
  1520. }
  1521. Asn1EndOfIndefiniteLengthNodeType DetectEndOfIndefiniteListContents(Stream xdata)
  1522. {
  1523. var tagByte = xdata.ReadByte();
  1524. if (tagByte != k_EndOfStream)
  1525. {
  1526. var lengthByte = xdata.ReadByte();
  1527. if (lengthByte != k_EndOfStream)
  1528. {
  1529. if (tagByte == Asn1Tag.TAG_END_OF_CONTENTS && lengthByte == Asn1Tag.TAG_END_OF_CONTENTS)
  1530. {
  1531. return Asn1EndOfIndefiniteLengthNodeType.EndOfNodeFooter;
  1532. }
  1533. else
  1534. {
  1535. return Asn1EndOfIndefiniteLengthNodeType.NotEnd;
  1536. }
  1537. }
  1538. }
  1539. return Asn1EndOfIndefiniteLengthNodeType.EndOfStream;
  1540. }
  1541. bool ReadNextChildNodeOfIndefiniteListClearIfInvalid(Stream xdata, ref long offset, long childNodeMaxLen)
  1542. {
  1543. xdata.Position -= k_IndefiniteLengthFooterSize;
  1544. bool validChildNode = false;
  1545. if (CreateAndAddChildNode(xdata, ref offset))
  1546. {
  1547. validChildNode = GetLastChild().DataLength < childNodeMaxLen;
  1548. }
  1549. if (ChildNodeCount > 0 && !validChildNode)
  1550. {
  1551. //DEVELOPERS' NOTE:
  1552. //Invalid sequential child Asn1Node found in an Indeterminate Length List Node.
  1553. //This Indeterminate Length List Node is a false flag that just happens to have initial bytes matching the pattern of such a node.
  1554. ClearAll();
  1555. }
  1556. return validChildNode;
  1557. }
  1558. /// <summary>
  1559. /// Set the node data and recalculate the entire tree parameters.
  1560. /// </summary>
  1561. /// <param name="xdata">byte[] data.</param>
  1562. protected void SetData(byte[] xdata)
  1563. {
  1564. if (childNodeList.Count > 0)
  1565. {
  1566. throw new Exception("Constructed node can't hold simple data.");
  1567. }
  1568. else
  1569. {
  1570. data = xdata;
  1571. if (data != null)
  1572. {
  1573. dataLength = data.Length;
  1574. }
  1575. else
  1576. {
  1577. dataLength = 0;
  1578. }
  1579. RecalculateTreePar();
  1580. }
  1581. }
  1582. /// <summary>
  1583. /// Load data from Stream. Start from current position.
  1584. /// </summary>
  1585. /// <param name="xdata">Stream</param>
  1586. /// <returns>true:Succeed; false:failed.</returns>
  1587. protected bool InternalLoadData(Stream xdata)
  1588. {
  1589. bool retval = true;
  1590. ClearAll();
  1591. byte xtag;
  1592. long curPosition = xdata.Position;
  1593. xtag = (byte)xdata.ReadByte();
  1594. xdata.Position = curPosition;
  1595. int maskedTag = xtag & Asn1Tag.TAG_MASK;
  1596. if (((xtag & Asn1TagClasses.CONSTRUCTED) != 0)
  1597. || (parseEncapsulatedData
  1598. && ((maskedTag == Asn1Tag.BIT_STRING)
  1599. || (maskedTag == Asn1Tag.EXTERNAL)
  1600. || (maskedTag == Asn1Tag.GENERAL_STRING)
  1601. || (maskedTag == Asn1Tag.GENERALIZED_TIME)
  1602. || (maskedTag == Asn1Tag.GRAPHIC_STRING)
  1603. || (maskedTag == Asn1Tag.IA5_STRING)
  1604. || (maskedTag == Asn1Tag.OCTET_STRING)
  1605. || (maskedTag == Asn1Tag.PRINTABLE_STRING)
  1606. || (maskedTag == Asn1Tag.SEQUENCE)
  1607. || (maskedTag == Asn1Tag.SET)
  1608. || (maskedTag == Asn1Tag.T61_STRING)
  1609. || (maskedTag == Asn1Tag.UNIVERSAL_STRING)
  1610. || (maskedTag == Asn1Tag.UTF8_STRING)
  1611. || (maskedTag == Asn1Tag.VIDEOTEXT_STRING)
  1612. || (maskedTag == Asn1Tag.VISIBLE_STRING)))
  1613. )
  1614. {
  1615. if (!ListDecode(xdata))
  1616. {
  1617. if (!GeneralDecode(xdata))
  1618. {
  1619. retval = false;
  1620. }
  1621. }
  1622. }
  1623. else
  1624. {
  1625. if (!GeneralDecode(xdata)) retval = false;
  1626. }
  1627. return retval;
  1628. }
  1629. /// <summary>
  1630. /// Get/Set parseEncapsulatedData. This property will be inherited by the
  1631. /// child nodes when loading data.
  1632. /// </summary>
  1633. public bool ParseEncapsulatedData
  1634. {
  1635. get
  1636. {
  1637. return parseEncapsulatedData;
  1638. }
  1639. set
  1640. {
  1641. if (parseEncapsulatedData == value) return;
  1642. byte[] tmpData = Data;
  1643. parseEncapsulatedData = value;
  1644. ClearAll();
  1645. if ((tag & Asn1TagClasses.CONSTRUCTED) != 0 || parseEncapsulatedData)
  1646. {
  1647. MemoryStream ms = new MemoryStream(tmpData);
  1648. ms.Position = 0;
  1649. bool isLoaded = true;
  1650. while (ms.Position < ms.Length)
  1651. {
  1652. Asn1Node tempNode = new Asn1Node();
  1653. tempNode.ParseEncapsulatedData = parseEncapsulatedData;
  1654. if (!tempNode.LoadData(ms))
  1655. {
  1656. ClearAll();
  1657. isLoaded = false;
  1658. break;
  1659. }
  1660. AddChild(tempNode);
  1661. }
  1662. if (!isLoaded)
  1663. {
  1664. Data = tmpData;
  1665. }
  1666. }
  1667. else
  1668. {
  1669. Data = tmpData;
  1670. }
  1671. }
  1672. }
  1673. }
  1674. }