AbstractTlsSecret.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto.Impl
  7. {
  8. /// <summary>Base class for a TlsSecret implementation which captures common code and fields.</summary>
  9. public abstract class AbstractTlsSecret
  10. : TlsSecret
  11. {
  12. protected static byte[] CopyData(AbstractTlsSecret other)
  13. {
  14. return other.CopyData();
  15. }
  16. protected byte[] m_data;
  17. /// <summary>Base constructor.</summary>
  18. /// <param name="data">the byte[] making up the secret value.</param>
  19. protected AbstractTlsSecret(byte[] data)
  20. {
  21. m_data = data;
  22. }
  23. protected virtual void CheckAlive()
  24. {
  25. if (m_data == null)
  26. throw new InvalidOperationException("Secret has already been extracted or destroyed");
  27. }
  28. protected abstract AbstractTlsCrypto Crypto { get; }
  29. public virtual byte[] CalculateHmac(int cryptoHashAlgorithm, byte[] buf, int off, int len)
  30. {
  31. lock (this)
  32. {
  33. CheckAlive();
  34. TlsHmac hmac = Crypto.CreateHmacForHash(cryptoHashAlgorithm);
  35. hmac.SetKey(m_data, 0, m_data.Length);
  36. hmac.Update(buf, off, len);
  37. return hmac.CalculateMac();
  38. }
  39. }
  40. public abstract TlsSecret DeriveUsingPrf(int prfAlgorithm, string label, byte[] seed, int length);
  41. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  42. public abstract TlsSecret DeriveUsingPrf(int prfAlgorithm, ReadOnlySpan<char> label, ReadOnlySpan<byte> seed,
  43. int length);
  44. #endif
  45. public virtual void Destroy()
  46. {
  47. lock (this)
  48. {
  49. if (m_data != null)
  50. {
  51. // TODO Is there a way to ensure the data is really overwritten?
  52. Array.Clear(m_data, 0, m_data.Length);
  53. m_data = null;
  54. }
  55. }
  56. }
  57. /// <exception cref="IOException"/>
  58. public virtual byte[] Encrypt(TlsEncryptor encryptor)
  59. {
  60. lock (this)
  61. {
  62. CheckAlive();
  63. return encryptor.Encrypt(m_data, 0, m_data.Length);
  64. }
  65. }
  66. public virtual byte[] Extract()
  67. {
  68. lock (this)
  69. {
  70. CheckAlive();
  71. byte[] result = m_data;
  72. m_data = null;
  73. return result;
  74. }
  75. }
  76. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  77. public virtual void ExtractTo(Span<byte> output)
  78. {
  79. lock (this)
  80. {
  81. CheckAlive();
  82. m_data.CopyTo(output);
  83. m_data = null;
  84. }
  85. }
  86. #endif
  87. public abstract TlsSecret HkdfExpand(int cryptoHashAlgorithm, byte[] info, int length);
  88. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  89. public abstract TlsSecret HkdfExpand(int cryptoHashAlgorithm, ReadOnlySpan<byte> info, int length);
  90. #endif
  91. public abstract TlsSecret HkdfExtract(int cryptoHashAlgorithm, TlsSecret ikm);
  92. public virtual bool IsAlive()
  93. {
  94. lock (this)
  95. {
  96. return null != m_data;
  97. }
  98. }
  99. public virtual int Length
  100. {
  101. get
  102. {
  103. lock (this)
  104. {
  105. CheckAlive();
  106. return m_data.Length;
  107. }
  108. }
  109. }
  110. internal virtual byte[] CopyData()
  111. {
  112. lock (this)
  113. {
  114. return Arrays.Clone(m_data);
  115. }
  116. }
  117. }
  118. }
  119. #pragma warning restore
  120. #endif