BcpgInputStream.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  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. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
  7. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Bcpg
  8. {
  9. /// <remarks>Reader for PGP objects.</remarks>
  10. public class BcpgInputStream
  11. : BaseInputStream
  12. {
  13. private Stream m_in;
  14. private bool next = false;
  15. private int nextB;
  16. internal static BcpgInputStream Wrap(
  17. Stream inStr)
  18. {
  19. if (inStr is BcpgInputStream)
  20. {
  21. return (BcpgInputStream) inStr;
  22. }
  23. return new BcpgInputStream(inStr);
  24. }
  25. private BcpgInputStream(
  26. Stream inputStream)
  27. {
  28. this.m_in = inputStream;
  29. }
  30. public override int ReadByte()
  31. {
  32. if (next)
  33. {
  34. next = false;
  35. return nextB;
  36. }
  37. return m_in.ReadByte();
  38. }
  39. public override int Read(byte[] buffer, int offset, int count)
  40. {
  41. if (!next)
  42. return m_in.Read(buffer, offset, count);
  43. Streams.ValidateBufferArguments(buffer, offset, count);
  44. if (nextB < 0)
  45. return 0;
  46. buffer[offset] = (byte)nextB;
  47. next = false;
  48. return 1;
  49. }
  50. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  51. public override int Read(Span<byte> buffer)
  52. {
  53. if (!next)
  54. return m_in.Read(buffer);
  55. if (nextB < 0)
  56. return 0;
  57. buffer[0] = (byte)nextB;
  58. next = false;
  59. return 1;
  60. }
  61. #endif
  62. public byte[] ReadAll()
  63. {
  64. return Streams.ReadAll(this);
  65. }
  66. public void ReadFully(byte[] buffer, int offset, int count)
  67. {
  68. if (Streams.ReadFully(this, buffer, offset, count) < count)
  69. throw new EndOfStreamException();
  70. }
  71. public void ReadFully(byte[] buffer)
  72. {
  73. ReadFully(buffer, 0, buffer.Length);
  74. }
  75. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  76. public void ReadFully(Span<byte> buffer)
  77. {
  78. if (Streams.ReadFully(this, buffer) < buffer.Length)
  79. throw new EndOfStreamException();
  80. }
  81. #endif
  82. /// <summary>Returns the next packet tag in the stream.</summary>
  83. public PacketTag NextPacketTag()
  84. {
  85. if (!next)
  86. {
  87. try
  88. {
  89. nextB = m_in.ReadByte();
  90. }
  91. catch (EndOfStreamException)
  92. {
  93. nextB = -1;
  94. }
  95. next = true;
  96. }
  97. if (nextB < 0)
  98. return (PacketTag)nextB;
  99. int maskB = nextB & 0x3f;
  100. if ((nextB & 0x40) == 0) // old
  101. {
  102. maskB >>= 2;
  103. }
  104. return (PacketTag)maskB;
  105. }
  106. public Packet ReadPacket()
  107. {
  108. int hdr = this.ReadByte();
  109. if (hdr < 0)
  110. {
  111. return null;
  112. }
  113. if ((hdr & 0x80) == 0)
  114. {
  115. throw new IOException("invalid header encountered");
  116. }
  117. bool newPacket = (hdr & 0x40) != 0;
  118. PacketTag tag = 0;
  119. int bodyLen = 0;
  120. bool partial = false;
  121. if (newPacket)
  122. {
  123. tag = (PacketTag)(hdr & 0x3f);
  124. int l = this.ReadByte();
  125. if (l < 192)
  126. {
  127. bodyLen = l;
  128. }
  129. else if (l <= 223)
  130. {
  131. int b = m_in.ReadByte();
  132. bodyLen = ((l - 192) << 8) + (b) + 192;
  133. }
  134. else if (l == 255)
  135. {
  136. bodyLen = (m_in.ReadByte() << 24) | (m_in.ReadByte() << 16)
  137. | (m_in.ReadByte() << 8) | m_in.ReadByte();
  138. }
  139. else
  140. {
  141. partial = true;
  142. bodyLen = 1 << (l & 0x1f);
  143. }
  144. }
  145. else
  146. {
  147. int lengthType = hdr & 0x3;
  148. tag = (PacketTag)((hdr & 0x3f) >> 2);
  149. switch (lengthType)
  150. {
  151. case 0:
  152. bodyLen = this.ReadByte();
  153. break;
  154. case 1:
  155. bodyLen = (this.ReadByte() << 8) | this.ReadByte();
  156. break;
  157. case 2:
  158. bodyLen = (this.ReadByte() << 24) | (this.ReadByte() << 16)
  159. | (this.ReadByte() << 8) | this.ReadByte();
  160. break;
  161. case 3:
  162. partial = true;
  163. break;
  164. default:
  165. throw new IOException("unknown length type encountered");
  166. }
  167. }
  168. BcpgInputStream objStream;
  169. if (bodyLen == 0 && partial)
  170. {
  171. objStream = this;
  172. }
  173. else
  174. {
  175. PartialInputStream pis = new PartialInputStream(this, partial, bodyLen);
  176. Stream buf = new BufferedStream(pis);
  177. objStream = new BcpgInputStream(buf);
  178. }
  179. switch (tag)
  180. {
  181. case PacketTag.Reserved:
  182. return new InputStreamPacket(objStream);
  183. case PacketTag.PublicKeyEncryptedSession:
  184. return new PublicKeyEncSessionPacket(objStream);
  185. case PacketTag.Signature:
  186. return new SignaturePacket(objStream);
  187. case PacketTag.SymmetricKeyEncryptedSessionKey:
  188. return new SymmetricKeyEncSessionPacket(objStream);
  189. case PacketTag.OnePassSignature:
  190. return new OnePassSignaturePacket(objStream);
  191. case PacketTag.SecretKey:
  192. return new SecretKeyPacket(objStream);
  193. case PacketTag.PublicKey:
  194. return new PublicKeyPacket(objStream);
  195. case PacketTag.SecretSubkey:
  196. return new SecretSubkeyPacket(objStream);
  197. case PacketTag.CompressedData:
  198. return new CompressedDataPacket(objStream);
  199. case PacketTag.SymmetricKeyEncrypted:
  200. return new SymmetricEncDataPacket(objStream);
  201. case PacketTag.Marker:
  202. return new MarkerPacket(objStream);
  203. case PacketTag.LiteralData:
  204. return new LiteralDataPacket(objStream);
  205. case PacketTag.Trust:
  206. return new TrustPacket(objStream);
  207. case PacketTag.UserId:
  208. return new UserIdPacket(objStream);
  209. case PacketTag.UserAttribute:
  210. return new UserAttributePacket(objStream);
  211. case PacketTag.PublicSubkey:
  212. return new PublicSubkeyPacket(objStream);
  213. case PacketTag.SymmetricEncryptedIntegrityProtected:
  214. return new SymmetricEncIntegrityPacket(objStream);
  215. case PacketTag.ModificationDetectionCode:
  216. return new ModDetectionCodePacket(objStream);
  217. case PacketTag.Experimental1:
  218. case PacketTag.Experimental2:
  219. case PacketTag.Experimental3:
  220. case PacketTag.Experimental4:
  221. return new ExperimentalPacket(tag, objStream);
  222. default:
  223. throw new IOException("unknown packet type encountered: " + tag);
  224. }
  225. }
  226. public PacketTag SkipMarkerPackets()
  227. {
  228. PacketTag tag;
  229. while ((tag = NextPacketTag()) == PacketTag.Marker)
  230. {
  231. ReadPacket();
  232. }
  233. return tag;
  234. }
  235. protected override void Dispose(bool disposing)
  236. {
  237. if (disposing)
  238. {
  239. m_in.Dispose();
  240. }
  241. base.Dispose(disposing);
  242. }
  243. /// <summary>
  244. /// A stream that overlays our input stream, allowing the user to only read a segment of it.
  245. /// NB: dataLength will be negative if the segment length is in the upper range above 2**31.
  246. /// </summary>
  247. private class PartialInputStream
  248. : BaseInputStream
  249. {
  250. private BcpgInputStream m_in;
  251. private bool partial;
  252. private int dataLength;
  253. internal PartialInputStream(
  254. BcpgInputStream bcpgIn,
  255. bool partial,
  256. int dataLength)
  257. {
  258. this.m_in = bcpgIn;
  259. this.partial = partial;
  260. this.dataLength = dataLength;
  261. }
  262. public override int ReadByte()
  263. {
  264. do
  265. {
  266. if (dataLength != 0)
  267. {
  268. int ch = m_in.ReadByte();
  269. if (ch < 0)
  270. {
  271. throw new EndOfStreamException("Premature end of stream in PartialInputStream");
  272. }
  273. dataLength--;
  274. return ch;
  275. }
  276. }
  277. while (partial && ReadPartialDataLength() >= 0);
  278. return -1;
  279. }
  280. public override int Read(byte[] buffer, int offset, int count)
  281. {
  282. Streams.ValidateBufferArguments(buffer, offset, count);
  283. do
  284. {
  285. if (dataLength != 0)
  286. {
  287. int readLen = (dataLength > count || dataLength < 0) ? count : dataLength;
  288. int len = m_in.Read(buffer, offset, readLen);
  289. if (len < 1)
  290. throw new EndOfStreamException("Premature end of stream in PartialInputStream");
  291. dataLength -= len;
  292. return len;
  293. }
  294. }
  295. while (partial && ReadPartialDataLength() >= 0);
  296. return 0;
  297. }
  298. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  299. public override int Read(Span<byte> buffer)
  300. {
  301. do
  302. {
  303. if (dataLength != 0)
  304. {
  305. int count = buffer.Length;
  306. int readLen = (dataLength > count || dataLength < 0) ? count : dataLength;
  307. int len = m_in.Read(buffer[..readLen]);
  308. if (len < 1)
  309. throw new EndOfStreamException("Premature end of stream in PartialInputStream");
  310. dataLength -= len;
  311. return len;
  312. }
  313. }
  314. while (partial && ReadPartialDataLength() >= 0);
  315. return 0;
  316. }
  317. #endif
  318. private int ReadPartialDataLength()
  319. {
  320. int l = m_in.ReadByte();
  321. if (l < 0)
  322. {
  323. return -1;
  324. }
  325. partial = false;
  326. if (l < 192)
  327. {
  328. dataLength = l;
  329. }
  330. else if (l <= 223)
  331. {
  332. dataLength = ((l - 192) << 8) + (m_in.ReadByte()) + 192;
  333. }
  334. else if (l == 255)
  335. {
  336. dataLength = (m_in.ReadByte() << 24) | (m_in.ReadByte() << 16)
  337. | (m_in.ReadByte() << 8) | m_in.ReadByte();
  338. }
  339. else
  340. {
  341. partial = true;
  342. dataLength = 1 << (l & 0x1f);
  343. }
  344. return 0;
  345. }
  346. }
  347. }
  348. }
  349. #pragma warning restore
  350. #endif