TlsDHUtilities.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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.Math;
  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 abstract class TlsDHUtilities
  11. {
  12. public static TlsDHConfig CreateNamedDHConfig(TlsContext context, int namedGroup)
  13. {
  14. if (namedGroup < 0 || NamedGroup.GetFiniteFieldBits(namedGroup) < 1)
  15. return null;
  16. bool padded = TlsUtilities.IsTlsV13(context);
  17. return new TlsDHConfig(namedGroup, padded);
  18. }
  19. public static DHGroup GetDHGroup(TlsDHConfig dhConfig)
  20. {
  21. int namedGroup = dhConfig.NamedGroup;
  22. if (namedGroup >= 0)
  23. return GetNamedDHGroup(namedGroup);
  24. return dhConfig.ExplicitGroup;
  25. }
  26. public static DHGroup GetNamedDHGroup(int namedGroup)
  27. {
  28. switch (namedGroup)
  29. {
  30. case NamedGroup.ffdhe2048:
  31. return DHStandardGroups.rfc7919_ffdhe2048;
  32. case NamedGroup.ffdhe3072:
  33. return DHStandardGroups.rfc7919_ffdhe3072;
  34. case NamedGroup.ffdhe4096:
  35. return DHStandardGroups.rfc7919_ffdhe4096;
  36. case NamedGroup.ffdhe6144:
  37. return DHStandardGroups.rfc7919_ffdhe6144;
  38. case NamedGroup.ffdhe8192:
  39. return DHStandardGroups.rfc7919_ffdhe8192;
  40. default:
  41. return null;
  42. }
  43. }
  44. public static int GetMinimumFiniteFieldBits(int cipherSuite)
  45. {
  46. /*
  47. * NOTE: An equivalent mechanism was added to support a minimum bit-size requirement for ECC
  48. * mooted in early drafts of RFC 8442. This requirement was removed in later drafts, so that
  49. * mechanism is currently somewhat trivial, and this similarly so.
  50. */
  51. return IsDHCipherSuite(cipherSuite) ? 1 : 0;
  52. }
  53. public static bool IsDHCipherSuite(int cipherSuite)
  54. {
  55. switch (TlsUtilities.GetKeyExchangeAlgorithm(cipherSuite))
  56. {
  57. case KeyExchangeAlgorithm.DH_anon:
  58. case KeyExchangeAlgorithm.DH_DSS:
  59. case KeyExchangeAlgorithm.DH_RSA:
  60. case KeyExchangeAlgorithm.DHE_DSS:
  61. case KeyExchangeAlgorithm.DHE_PSK:
  62. case KeyExchangeAlgorithm.DHE_RSA:
  63. return true;
  64. default:
  65. return false;
  66. }
  67. }
  68. public static int GetNamedGroupForDHParameters(BigInteger p, BigInteger g)
  69. {
  70. int[] namedGroups = new int[]{ NamedGroup.ffdhe2048, NamedGroup.ffdhe3072, NamedGroup.ffdhe4096,
  71. NamedGroup.ffdhe6144, NamedGroup.ffdhe8192 };
  72. for (int i = 0; i < namedGroups.Length; ++i)
  73. {
  74. int namedGroup = namedGroups[i];
  75. DHGroup dhGroup = GetNamedDHGroup(namedGroup);
  76. if (dhGroup != null && dhGroup.P.Equals(p) && dhGroup.G.Equals(g))
  77. return namedGroup;
  78. }
  79. return -1;
  80. }
  81. public static DHGroup GetStandardGroupForDHParameters(BigInteger p, BigInteger g)
  82. {
  83. DHGroup[] standardGroups = new DHGroup[] { DHStandardGroups.rfc7919_ffdhe2048,
  84. DHStandardGroups.rfc7919_ffdhe3072, DHStandardGroups.rfc7919_ffdhe4096, DHStandardGroups.rfc7919_ffdhe6144,
  85. DHStandardGroups.rfc7919_ffdhe8192, DHStandardGroups.rfc3526_1536, DHStandardGroups.rfc3526_2048,
  86. DHStandardGroups.rfc3526_3072, DHStandardGroups.rfc3526_4096, DHStandardGroups.rfc3526_6144,
  87. DHStandardGroups.rfc3526_8192, DHStandardGroups.rfc5996_768, DHStandardGroups.rfc5996_1024 };
  88. for (int i = 0; i < standardGroups.Length; ++i)
  89. {
  90. DHGroup dhGroup = standardGroups[i];
  91. if (dhGroup != null && dhGroup.P.Equals(p) && dhGroup.G.Equals(g))
  92. return dhGroup;
  93. }
  94. return null;
  95. }
  96. /// <exception cref="IOException"/>
  97. public static TlsDHConfig ReceiveDHConfig(TlsContext context, TlsDHGroupVerifier dhGroupVerifier,
  98. Stream input)
  99. {
  100. BigInteger p = ReadDHParameter(input);
  101. BigInteger g = ReadDHParameter(input);
  102. int namedGroup = GetNamedGroupForDHParameters(p, g);
  103. if (namedGroup< 0)
  104. {
  105. DHGroup dhGroup = GetStandardGroupForDHParameters(p, g);
  106. if (null == dhGroup)
  107. {
  108. dhGroup = new DHGroup(p, null, g, 0);
  109. }
  110. if (!dhGroupVerifier.Accept(dhGroup))
  111. throw new TlsFatalAlert(AlertDescription.insufficient_security);
  112. return new TlsDHConfig(dhGroup);
  113. }
  114. int[] clientSupportedGroups = context.SecurityParameters.ClientSupportedGroups;
  115. if (null == clientSupportedGroups || Arrays.Contains(clientSupportedGroups, namedGroup))
  116. return new TlsDHConfig(namedGroup, false);
  117. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  118. }
  119. /// <exception cref="IOException"/>
  120. public static BigInteger ReadDHParameter(Stream input)
  121. {
  122. return new BigInteger(1, TlsUtilities.ReadOpaque16(input, 1));
  123. }
  124. /// <exception cref="IOException"/>
  125. public static void WriteDHConfig(TlsDHConfig dhConfig, Stream output)
  126. {
  127. DHGroup group = GetDHGroup(dhConfig);
  128. WriteDHParameter(group.P, output);
  129. WriteDHParameter(group.G, output);
  130. }
  131. /// <exception cref="IOException"/>
  132. public static void WriteDHParameter(BigInteger x, Stream output)
  133. {
  134. TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(x), output);
  135. }
  136. }
  137. }
  138. #pragma warning restore
  139. #endif