OfferedPsks.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using System.IO;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  8. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Tls
  9. {
  10. public sealed class OfferedPsks
  11. {
  12. internal class BindersConfig
  13. {
  14. internal readonly TlsPsk[] m_psks;
  15. internal readonly short[] m_pskKeyExchangeModes;
  16. internal readonly TlsSecret[] m_earlySecrets;
  17. internal int m_bindersSize;
  18. internal BindersConfig(TlsPsk[] psks, short[] pskKeyExchangeModes, TlsSecret[] earlySecrets,
  19. int bindersSize)
  20. {
  21. this.m_psks = psks;
  22. this.m_pskKeyExchangeModes = pskKeyExchangeModes;
  23. this.m_earlySecrets = earlySecrets;
  24. this.m_bindersSize = bindersSize;
  25. }
  26. }
  27. internal class SelectedConfig
  28. {
  29. internal readonly int m_index;
  30. internal readonly TlsPsk m_psk;
  31. internal readonly short[] m_pskKeyExchangeModes;
  32. internal readonly TlsSecret m_earlySecret;
  33. internal SelectedConfig(int index, TlsPsk psk, short[] pskKeyExchangeModes, TlsSecret earlySecret)
  34. {
  35. this.m_index = index;
  36. this.m_psk = psk;
  37. this.m_pskKeyExchangeModes = pskKeyExchangeModes;
  38. this.m_earlySecret = earlySecret;
  39. }
  40. }
  41. private readonly IList m_identities;
  42. private readonly IList m_binders;
  43. private readonly int m_bindersSize;
  44. public OfferedPsks(IList identities)
  45. : this(identities, null, -1)
  46. {
  47. }
  48. private OfferedPsks(IList identities, IList binders, int bindersSize)
  49. {
  50. if (null == identities || identities.Count < 1)
  51. throw new ArgumentException("cannot be null or empty", "identities");
  52. if (null != binders && identities.Count != binders.Count)
  53. throw new ArgumentException("must be the same length as 'identities' (or null)", "binders");
  54. if ((null != binders) != (bindersSize >= 0))
  55. throw new ArgumentException("must be >= 0 iff 'binders' are present", "bindersSize");
  56. this.m_identities = identities;
  57. this.m_binders = binders;
  58. this.m_bindersSize = bindersSize;
  59. }
  60. public IList Binders
  61. {
  62. get { return m_binders; }
  63. }
  64. public int BindersSize
  65. {
  66. get { return m_bindersSize; }
  67. }
  68. public IList Identities
  69. {
  70. get { return m_identities; }
  71. }
  72. public int GetIndexOfIdentity(PskIdentity pskIdentity)
  73. {
  74. for (int i = 0, count = m_identities.Count; i < count; ++i)
  75. {
  76. if (pskIdentity.Equals(m_identities[i]))
  77. return i;
  78. }
  79. return -1;
  80. }
  81. /// <exception cref="IOException"/>
  82. public void Encode(Stream output)
  83. {
  84. // identities
  85. {
  86. int lengthOfIdentitiesList = 0;
  87. foreach (PskIdentity identity in m_identities)
  88. {
  89. lengthOfIdentitiesList += identity.GetEncodedLength();
  90. }
  91. TlsUtilities.CheckUint16(lengthOfIdentitiesList);
  92. TlsUtilities.WriteUint16(lengthOfIdentitiesList, output);
  93. foreach (PskIdentity identity in m_identities)
  94. {
  95. identity.Encode(output);
  96. }
  97. }
  98. // binders
  99. if (null != m_binders)
  100. {
  101. int lengthOfBindersList = 0;
  102. foreach (byte[] binder in m_binders)
  103. {
  104. lengthOfBindersList += 1 + binder.Length;
  105. }
  106. TlsUtilities.CheckUint16(lengthOfBindersList);
  107. TlsUtilities.WriteUint16(lengthOfBindersList, output);
  108. foreach (byte[] binder in m_binders)
  109. {
  110. TlsUtilities.WriteOpaque8(binder, output);
  111. }
  112. }
  113. }
  114. /// <exception cref="IOException"/>
  115. internal static void EncodeBinders(Stream output, TlsCrypto crypto, TlsHandshakeHash handshakeHash,
  116. BindersConfig bindersConfig)
  117. {
  118. TlsPsk[] psks = bindersConfig.m_psks;
  119. TlsSecret[] earlySecrets = bindersConfig.m_earlySecrets;
  120. int expectedLengthOfBindersList = bindersConfig.m_bindersSize - 2;
  121. TlsUtilities.CheckUint16(expectedLengthOfBindersList);
  122. TlsUtilities.WriteUint16(expectedLengthOfBindersList, output);
  123. int lengthOfBindersList = 0;
  124. for (int i = 0; i < psks.Length; ++i)
  125. {
  126. TlsPsk psk = psks[i];
  127. TlsSecret earlySecret = earlySecrets[i];
  128. // TODO[tls13-psk] Handle resumption PSKs
  129. bool isExternalPsk = true;
  130. int pskCryptoHashAlgorithm = TlsCryptoUtilities.GetHashForPrf(psk.PrfAlgorithm);
  131. // TODO[tls13-psk] Cache the transcript hashes per algorithm to avoid duplicates for multiple PSKs
  132. TlsHash hash = crypto.CreateHash(pskCryptoHashAlgorithm);
  133. handshakeHash.CopyBufferTo(new TlsHashSink(hash));
  134. byte[] transcriptHash = hash.CalculateHash();
  135. byte[] binder = TlsUtilities.CalculatePskBinder(crypto, isExternalPsk, pskCryptoHashAlgorithm,
  136. earlySecret, transcriptHash);
  137. lengthOfBindersList += 1 + binder.Length;
  138. TlsUtilities.WriteOpaque8(binder, output);
  139. }
  140. if (expectedLengthOfBindersList != lengthOfBindersList)
  141. throw new TlsFatalAlert(AlertDescription.internal_error);
  142. }
  143. /// <exception cref="IOException"/>
  144. internal static int GetBindersSize(TlsPsk[] psks)
  145. {
  146. int lengthOfBindersList = 0;
  147. for (int i = 0; i < psks.Length; ++i)
  148. {
  149. TlsPsk psk = psks[i];
  150. int prfAlgorithm = psk.PrfAlgorithm;
  151. int prfCryptoHashAlgorithm = TlsCryptoUtilities.GetHashForPrf(prfAlgorithm);
  152. lengthOfBindersList += 1 + TlsCryptoUtilities.GetHashOutputSize(prfCryptoHashAlgorithm);
  153. }
  154. TlsUtilities.CheckUint16(lengthOfBindersList);
  155. return 2 + lengthOfBindersList;
  156. }
  157. /// <exception cref="IOException"/>
  158. public static OfferedPsks Parse(Stream input)
  159. {
  160. IList identities = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
  161. {
  162. int totalLengthIdentities = TlsUtilities.ReadUint16(input);
  163. if (totalLengthIdentities < 7)
  164. throw new TlsFatalAlert(AlertDescription.decode_error);
  165. byte[] identitiesData = TlsUtilities.ReadFully(totalLengthIdentities, input);
  166. MemoryStream buf = new MemoryStream(identitiesData, false);
  167. do
  168. {
  169. PskIdentity identity = PskIdentity.Parse(buf);
  170. identities.Add(identity);
  171. }
  172. while (buf.Position < buf.Length);
  173. }
  174. IList binders = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
  175. int totalLengthBinders = TlsUtilities.ReadUint16(input);
  176. {
  177. if (totalLengthBinders < 33)
  178. throw new TlsFatalAlert(AlertDescription.decode_error);
  179. byte[] bindersData = TlsUtilities.ReadFully(totalLengthBinders, input);
  180. MemoryStream buf = new MemoryStream(bindersData, false);
  181. do
  182. {
  183. byte[] binder = TlsUtilities.ReadOpaque8(buf, 32);
  184. binders.Add(binder);
  185. }
  186. while (buf.Position < buf.Length);
  187. }
  188. return new OfferedPsks(identities, binders, 2 + totalLengthBinders);
  189. }
  190. }
  191. }
  192. #pragma warning restore
  193. #endif