HeartbeatMessage.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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.Utilities;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Tls
  8. {
  9. public class HeartbeatMessage
  10. {
  11. protected readonly byte mType;
  12. protected readonly byte[] mPayload;
  13. protected readonly int mPaddingLength;
  14. public HeartbeatMessage(byte type, byte[] payload, int paddingLength)
  15. {
  16. if (!HeartbeatMessageType.IsValid(type))
  17. throw new ArgumentException("not a valid HeartbeatMessageType value", "type");
  18. if (payload == null || payload.Length >= (1 << 16))
  19. throw new ArgumentException("must have length < 2^16", "payload");
  20. if (paddingLength < 16)
  21. throw new ArgumentException("must be at least 16", "paddingLength");
  22. this.mType = type;
  23. this.mPayload = payload;
  24. this.mPaddingLength = paddingLength;
  25. }
  26. /**
  27. * Encode this {@link HeartbeatMessage} to a {@link Stream}.
  28. *
  29. * @param output
  30. * the {@link Stream} to encode to.
  31. * @throws IOException
  32. */
  33. public virtual void Encode(TlsContext context, Stream output)
  34. {
  35. TlsUtilities.WriteUint8(mType, output);
  36. TlsUtilities.CheckUint16(mPayload.Length);
  37. TlsUtilities.WriteUint16(mPayload.Length, output);
  38. output.Write(mPayload, 0, mPayload.Length);
  39. byte[] padding = new byte[mPaddingLength];
  40. context.NonceRandomGenerator.NextBytes(padding);
  41. output.Write(padding, 0, padding.Length);
  42. }
  43. /**
  44. * Parse a {@link HeartbeatMessage} from a {@link Stream}.
  45. *
  46. * @param input
  47. * the {@link Stream} to parse from.
  48. * @return a {@link HeartbeatMessage} object.
  49. * @throws IOException
  50. */
  51. public static HeartbeatMessage Parse(Stream input)
  52. {
  53. byte type = TlsUtilities.ReadUint8(input);
  54. if (!HeartbeatMessageType.IsValid(type))
  55. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  56. int payload_length = TlsUtilities.ReadUint16(input);
  57. PayloadBuffer buf = new PayloadBuffer();
  58. Streams.PipeAll(input, buf);
  59. byte[] payload = buf.ToTruncatedByteArray(payload_length);
  60. if (payload == null)
  61. {
  62. /*
  63. * RFC 6520 4. If the payload_length of a received HeartbeatMessage is too large, the
  64. * received HeartbeatMessage MUST be discarded silently.
  65. */
  66. return null;
  67. }
  68. TlsUtilities.CheckUint16(buf.Length);
  69. int padding_length = (int)buf.Length - payload.Length;
  70. /*
  71. * RFC 6520 4. The padding of a received HeartbeatMessage message MUST be ignored
  72. */
  73. return new HeartbeatMessage(type, payload, padding_length);
  74. }
  75. internal class PayloadBuffer
  76. : MemoryStream
  77. {
  78. internal byte[] ToTruncatedByteArray(int payloadLength)
  79. {
  80. /*
  81. * RFC 6520 4. The padding_length MUST be at least 16.
  82. */
  83. int minimumCount = payloadLength + 16;
  84. if (Length < minimumCount)
  85. return null;
  86. #if PORTABLE || NETFX_CORE
  87. byte[] buf = ToArray();
  88. #else
  89. byte[] buf = GetBuffer();
  90. #endif
  91. return Arrays.CopyOf(buf, payloadLength);
  92. }
  93. }
  94. }
  95. }
  96. #pragma warning restore
  97. #endif