BcpgInputStream.cs 11 KB

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