TlsRsaUtilities.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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.Crypto.Encodings;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  9. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  10. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Tls
  11. {
  12. public abstract class TlsRsaUtilities
  13. {
  14. /// <exception cref="IOException"></exception>
  15. public static byte[] GenerateEncryptedPreMasterSecret(TlsContext context, RsaKeyParameters rsaServerPublicKey,
  16. Stream output)
  17. {
  18. /*
  19. * Choose a PremasterSecret and send it encrypted to the server
  20. */
  21. byte[] premasterSecret = new byte[48];
  22. context.SecureRandom.NextBytes(premasterSecret);
  23. TlsUtilities.WriteVersion(context.ClientVersion, premasterSecret, 0);
  24. Pkcs1Encoding encoding = new Pkcs1Encoding(new RsaBlindedEngine());
  25. encoding.Init(true, new ParametersWithRandom(rsaServerPublicKey, context.SecureRandom));
  26. try
  27. {
  28. byte[] encryptedPreMasterSecret = encoding.ProcessBlock(premasterSecret, 0, premasterSecret.Length);
  29. if (TlsUtilities.IsSsl(context))
  30. {
  31. // TODO Do any SSLv3 servers actually expect the length?
  32. output.Write(encryptedPreMasterSecret, 0, encryptedPreMasterSecret.Length);
  33. }
  34. else
  35. {
  36. TlsUtilities.WriteOpaque16(encryptedPreMasterSecret, output);
  37. }
  38. }
  39. catch (InvalidCipherTextException e)
  40. {
  41. /*
  42. * This should never happen, only during decryption.
  43. */
  44. throw new TlsFatalAlert(AlertDescription.internal_error, e);
  45. }
  46. return premasterSecret;
  47. }
  48. public static byte[] SafeDecryptPreMasterSecret(TlsContext context, RsaKeyParameters rsaServerPrivateKey,
  49. byte[] encryptedPreMasterSecret)
  50. {
  51. /*
  52. * RFC 5246 7.4.7.1.
  53. */
  54. ProtocolVersion clientVersion = context.ClientVersion;
  55. // TODO Provide as configuration option?
  56. bool versionNumberCheckDisabled = false;
  57. /*
  58. * Generate 48 random bytes we can use as a Pre-Master-Secret, if the
  59. * PKCS1 padding check should fail.
  60. */
  61. byte[] fallback = new byte[48];
  62. context.SecureRandom.NextBytes(fallback);
  63. byte[] M = Arrays.Clone(fallback);
  64. try
  65. {
  66. Pkcs1Encoding encoding = new Pkcs1Encoding(new RsaBlindedEngine(), fallback);
  67. encoding.Init(false,
  68. new ParametersWithRandom(rsaServerPrivateKey, context.SecureRandom));
  69. M = encoding.ProcessBlock(encryptedPreMasterSecret, 0, encryptedPreMasterSecret.Length);
  70. }
  71. catch (Exception)
  72. {
  73. /*
  74. * This should never happen since the decryption should never throw an exception
  75. * and return a random value instead.
  76. *
  77. * In any case, a TLS server MUST NOT generate an alert if processing an
  78. * RSA-encrypted premaster secret message fails, or the version number is not as
  79. * expected. Instead, it MUST continue the handshake with a randomly generated
  80. * premaster secret.
  81. */
  82. }
  83. /*
  84. * If ClientHello.client_version is TLS 1.1 or higher, server implementations MUST
  85. * check the version number [..].
  86. */
  87. if (versionNumberCheckDisabled && clientVersion.IsEqualOrEarlierVersionOf(ProtocolVersion.TLSv10))
  88. {
  89. /*
  90. * If the version number is TLS 1.0 or earlier, server
  91. * implementations SHOULD check the version number, but MAY have a
  92. * configuration option to disable the check.
  93. *
  94. * So there is nothing to do here.
  95. */
  96. }
  97. else
  98. {
  99. /*
  100. * OK, we need to compare the version number in the decrypted Pre-Master-Secret with the
  101. * clientVersion received during the handshake. If they don't match, we replace the
  102. * decrypted Pre-Master-Secret with a random one.
  103. */
  104. int correct = (clientVersion.MajorVersion ^ (M[0] & 0xff))
  105. | (clientVersion.MinorVersion ^ (M[1] & 0xff));
  106. correct |= correct >> 1;
  107. correct |= correct >> 2;
  108. correct |= correct >> 4;
  109. int mask = ~((correct & 1) - 1);
  110. /*
  111. * mask will be all bits set to 0xff if the version number differed.
  112. */
  113. for (int i = 0; i < 48; i++)
  114. {
  115. M[i] = (byte)((M[i] & (~mask)) | (fallback[i] & mask));
  116. }
  117. }
  118. return M;
  119. }
  120. }
  121. }
  122. #pragma warning restore
  123. #endif