TlsRsaUtilities.cs 5.1 KB

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