TlsPskKeyExchange.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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.Tls.Crypto;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Tls
  8. {
  9. /// <summary>(D)TLS PSK key exchange (RFC 4279).</summary>
  10. public class TlsPskKeyExchange
  11. : AbstractTlsKeyExchange
  12. {
  13. private static int CheckKeyExchange(int keyExchange)
  14. {
  15. switch (keyExchange)
  16. {
  17. case KeyExchangeAlgorithm.DHE_PSK:
  18. case KeyExchangeAlgorithm.ECDHE_PSK:
  19. case KeyExchangeAlgorithm.PSK:
  20. case KeyExchangeAlgorithm.RSA_PSK:
  21. return keyExchange;
  22. default:
  23. throw new ArgumentException("unsupported key exchange algorithm", "keyExchange");
  24. }
  25. }
  26. protected TlsPskIdentity m_pskIdentity;
  27. protected TlsPskIdentityManager m_pskIdentityManager;
  28. protected TlsDHGroupVerifier m_dhGroupVerifier;
  29. protected byte[] m_psk_identity_hint = null;
  30. protected byte[] m_psk = null;
  31. protected TlsDHConfig m_dhConfig;
  32. protected TlsECConfig m_ecConfig;
  33. protected TlsAgreement m_agreement;
  34. protected TlsCredentialedDecryptor m_serverCredentials = null;
  35. protected TlsEncryptor m_serverEncryptor;
  36. protected TlsSecret m_preMasterSecret;
  37. public TlsPskKeyExchange(int keyExchange, TlsPskIdentity pskIdentity, TlsDHGroupVerifier dhGroupVerifier)
  38. : this(keyExchange, pskIdentity, null, dhGroupVerifier, null, null)
  39. {
  40. }
  41. public TlsPskKeyExchange(int keyExchange, TlsPskIdentityManager pskIdentityManager,
  42. TlsDHConfig dhConfig, TlsECConfig ecConfig)
  43. : this(keyExchange, null, pskIdentityManager, null, dhConfig, ecConfig)
  44. {
  45. }
  46. private TlsPskKeyExchange(int keyExchange, TlsPskIdentity pskIdentity, TlsPskIdentityManager pskIdentityManager,
  47. TlsDHGroupVerifier dhGroupVerifier, TlsDHConfig dhConfig, TlsECConfig ecConfig)
  48. : base(CheckKeyExchange(keyExchange))
  49. {
  50. this.m_pskIdentity = pskIdentity;
  51. this.m_pskIdentityManager = pskIdentityManager;
  52. this.m_dhGroupVerifier = dhGroupVerifier;
  53. this.m_dhConfig = dhConfig;
  54. this.m_ecConfig = ecConfig;
  55. }
  56. public override void SkipServerCredentials()
  57. {
  58. if (m_keyExchange == KeyExchangeAlgorithm.RSA_PSK)
  59. throw new TlsFatalAlert(AlertDescription.internal_error);
  60. }
  61. public override void ProcessServerCredentials(TlsCredentials serverCredentials)
  62. {
  63. if (m_keyExchange != KeyExchangeAlgorithm.RSA_PSK)
  64. throw new TlsFatalAlert(AlertDescription.internal_error);
  65. this.m_serverCredentials = TlsUtilities.RequireDecryptorCredentials(serverCredentials);
  66. }
  67. public override void ProcessServerCertificate(Certificate serverCertificate)
  68. {
  69. if (m_keyExchange != KeyExchangeAlgorithm.RSA_PSK)
  70. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  71. this.m_serverEncryptor = serverCertificate.GetCertificateAt(0).CreateEncryptor(
  72. TlsCertificateRole.RsaEncryption);
  73. }
  74. public override byte[] GenerateServerKeyExchange()
  75. {
  76. this.m_psk_identity_hint = m_pskIdentityManager.GetHint();
  77. if (this.m_psk_identity_hint == null && !RequiresServerKeyExchange)
  78. return null;
  79. MemoryStream buf = new MemoryStream();
  80. if (this.m_psk_identity_hint == null)
  81. {
  82. TlsUtilities.WriteOpaque16(TlsUtilities.EmptyBytes, buf);
  83. }
  84. else
  85. {
  86. TlsUtilities.WriteOpaque16(this.m_psk_identity_hint, buf);
  87. }
  88. if (this.m_keyExchange == KeyExchangeAlgorithm.DHE_PSK)
  89. {
  90. if (this.m_dhConfig == null)
  91. throw new TlsFatalAlert(AlertDescription.internal_error);
  92. TlsDHUtilities.WriteDHConfig(m_dhConfig, buf);
  93. this.m_agreement = m_context.Crypto.CreateDHDomain(m_dhConfig).CreateDH();
  94. GenerateEphemeralDH(buf);
  95. }
  96. else if (this.m_keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
  97. {
  98. if (this.m_ecConfig == null)
  99. throw new TlsFatalAlert(AlertDescription.internal_error);
  100. TlsEccUtilities.WriteECConfig(m_ecConfig, buf);
  101. this.m_agreement = m_context.Crypto.CreateECDomain(m_ecConfig).CreateECDH();
  102. GenerateEphemeralECDH(buf);
  103. }
  104. return buf.ToArray();
  105. }
  106. public override bool RequiresServerKeyExchange
  107. {
  108. get
  109. {
  110. switch (m_keyExchange)
  111. {
  112. case KeyExchangeAlgorithm.DHE_PSK:
  113. case KeyExchangeAlgorithm.ECDHE_PSK:
  114. return true;
  115. default:
  116. return false;
  117. }
  118. }
  119. }
  120. public override void ProcessServerKeyExchange(Stream input)
  121. {
  122. this.m_psk_identity_hint = TlsUtilities.ReadOpaque16(input);
  123. if (this.m_keyExchange == KeyExchangeAlgorithm.DHE_PSK)
  124. {
  125. this.m_dhConfig = TlsDHUtilities.ReceiveDHConfig(m_context, m_dhGroupVerifier, input);
  126. byte[] y = TlsUtilities.ReadOpaque16(input, 1);
  127. this.m_agreement = m_context.Crypto.CreateDHDomain(m_dhConfig).CreateDH();
  128. ProcessEphemeralDH(y);
  129. }
  130. else if (this.m_keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
  131. {
  132. this.m_ecConfig = TlsEccUtilities.ReceiveECDHConfig(m_context, input);
  133. byte[] point = TlsUtilities.ReadOpaque8(input, 1);
  134. this.m_agreement = m_context.Crypto.CreateECDomain(m_ecConfig).CreateECDH();
  135. ProcessEphemeralECDH(point);
  136. }
  137. }
  138. public override void ProcessClientCredentials(TlsCredentials clientCredentials)
  139. {
  140. throw new TlsFatalAlert(AlertDescription.internal_error);
  141. }
  142. public override void GenerateClientKeyExchange(Stream output)
  143. {
  144. if (m_psk_identity_hint == null)
  145. {
  146. m_pskIdentity.SkipIdentityHint();
  147. }
  148. else
  149. {
  150. m_pskIdentity.NotifyIdentityHint(m_psk_identity_hint);
  151. }
  152. byte[] psk_identity = m_pskIdentity.GetPskIdentity();
  153. if (psk_identity == null)
  154. throw new TlsFatalAlert(AlertDescription.internal_error);
  155. this.m_psk = m_pskIdentity.GetPsk();
  156. if (m_psk == null)
  157. throw new TlsFatalAlert(AlertDescription.internal_error);
  158. TlsUtilities.WriteOpaque16(psk_identity, output);
  159. m_context.SecurityParameters.m_pskIdentity = Arrays.Clone(psk_identity);
  160. if (this.m_keyExchange == KeyExchangeAlgorithm.DHE_PSK)
  161. {
  162. GenerateEphemeralDH(output);
  163. }
  164. else if (this.m_keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
  165. {
  166. GenerateEphemeralECDH(output);
  167. }
  168. else if (this.m_keyExchange == KeyExchangeAlgorithm.RSA_PSK)
  169. {
  170. this.m_preMasterSecret = TlsUtilities.GenerateEncryptedPreMasterSecret(m_context, m_serverEncryptor,
  171. output);
  172. }
  173. }
  174. public override void ProcessClientKeyExchange(Stream input)
  175. {
  176. byte[] psk_identity = TlsUtilities.ReadOpaque16(input);
  177. this.m_psk = m_pskIdentityManager.GetPsk(psk_identity);
  178. if (m_psk == null)
  179. throw new TlsFatalAlert(AlertDescription.unknown_psk_identity);
  180. m_context.SecurityParameters.m_pskIdentity = psk_identity;
  181. if (this.m_keyExchange == KeyExchangeAlgorithm.DHE_PSK)
  182. {
  183. byte[] y = TlsUtilities.ReadOpaque16(input, 1);
  184. ProcessEphemeralDH(y);
  185. }
  186. else if (this.m_keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
  187. {
  188. byte[] point = TlsUtilities.ReadOpaque8(input, 1);
  189. ProcessEphemeralECDH(point);
  190. }
  191. else if (this.m_keyExchange == KeyExchangeAlgorithm.RSA_PSK)
  192. {
  193. byte[] encryptedPreMasterSecret = TlsUtilities.ReadEncryptedPms(m_context, input);
  194. this.m_preMasterSecret = m_serverCredentials.Decrypt(new TlsCryptoParameters(m_context),
  195. encryptedPreMasterSecret);
  196. }
  197. }
  198. public override TlsSecret GeneratePreMasterSecret()
  199. {
  200. byte[] other_secret = GenerateOtherSecret(m_psk.Length);
  201. MemoryStream buf = new MemoryStream(4 + other_secret.Length + m_psk.Length);
  202. TlsUtilities.WriteOpaque16(other_secret, buf);
  203. TlsUtilities.WriteOpaque16(m_psk, buf);
  204. Array.Clear(m_psk, 0, m_psk.Length);
  205. this.m_psk = null;
  206. return m_context.Crypto.CreateSecret(buf.ToArray());
  207. }
  208. protected virtual void GenerateEphemeralDH(Stream output)
  209. {
  210. byte[] y = m_agreement.GenerateEphemeral();
  211. TlsUtilities.WriteOpaque16(y, output);
  212. }
  213. protected virtual void GenerateEphemeralECDH(Stream output)
  214. {
  215. byte[] point = m_agreement.GenerateEphemeral();
  216. TlsUtilities.WriteOpaque8(point, output);
  217. }
  218. protected virtual byte[] GenerateOtherSecret(int pskLength)
  219. {
  220. if (this.m_keyExchange == KeyExchangeAlgorithm.PSK)
  221. return new byte[pskLength];
  222. if (this.m_keyExchange == KeyExchangeAlgorithm.DHE_PSK ||
  223. this.m_keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
  224. {
  225. if (m_agreement != null)
  226. return m_agreement.CalculateSecret().Extract();
  227. }
  228. if (this.m_keyExchange == KeyExchangeAlgorithm.RSA_PSK)
  229. {
  230. if (m_preMasterSecret != null)
  231. return this.m_preMasterSecret.Extract();
  232. }
  233. throw new TlsFatalAlert(AlertDescription.internal_error);
  234. }
  235. protected virtual void ProcessEphemeralDH(byte[] y)
  236. {
  237. this.m_agreement.ReceivePeerValue(y);
  238. }
  239. protected virtual void ProcessEphemeralECDH(byte[] point)
  240. {
  241. TlsEccUtilities.CheckPointEncoding(m_ecConfig.NamedGroup, point);
  242. this.m_agreement.ReceivePeerValue(point);
  243. }
  244. }
  245. }
  246. #pragma warning restore
  247. #endif