TlsDHKeyExchange.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. using Org.BouncyCastle.Asn1.X509;
  6. using Org.BouncyCastle.Crypto.Parameters;
  7. using Org.BouncyCastle.Math;
  8. using Org.BouncyCastle.Security;
  9. namespace Org.BouncyCastle.Crypto.Tls
  10. {
  11. /// <summary>(D)TLS DH key exchange.</summary>
  12. public class TlsDHKeyExchange
  13. : AbstractTlsKeyExchange
  14. {
  15. protected TlsSigner mTlsSigner;
  16. protected DHParameters mDHParameters;
  17. protected AsymmetricKeyParameter mServerPublicKey;
  18. protected TlsAgreementCredentials mAgreementCredentials;
  19. protected DHPrivateKeyParameters mDHAgreePrivateKey;
  20. protected DHPublicKeyParameters mDHAgreePublicKey;
  21. public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
  22. : base(keyExchange, supportedSignatureAlgorithms)
  23. {
  24. switch (keyExchange)
  25. {
  26. case KeyExchangeAlgorithm.DH_RSA:
  27. case KeyExchangeAlgorithm.DH_DSS:
  28. this.mTlsSigner = null;
  29. break;
  30. case KeyExchangeAlgorithm.DHE_RSA:
  31. this.mTlsSigner = new TlsRsaSigner();
  32. break;
  33. case KeyExchangeAlgorithm.DHE_DSS:
  34. this.mTlsSigner = new TlsDssSigner();
  35. break;
  36. default:
  37. throw new InvalidOperationException("unsupported key exchange algorithm");
  38. }
  39. this.mDHParameters = dhParameters;
  40. }
  41. public override void Init(TlsContext context)
  42. {
  43. base.Init(context);
  44. if (this.mTlsSigner != null)
  45. {
  46. this.mTlsSigner.Init(context);
  47. }
  48. }
  49. public override void SkipServerCredentials()
  50. {
  51. throw new TlsFatalAlert(AlertDescription.unexpected_message);
  52. }
  53. public override void ProcessServerCertificate(Certificate serverCertificate)
  54. {
  55. if (serverCertificate.IsEmpty)
  56. throw new TlsFatalAlert(AlertDescription.bad_certificate);
  57. X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
  58. SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
  59. try
  60. {
  61. this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo);
  62. }
  63. catch (Exception e)
  64. {
  65. throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e);
  66. }
  67. if (mTlsSigner == null)
  68. {
  69. try
  70. {
  71. this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey);
  72. this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
  73. }
  74. catch (InvalidCastException e)
  75. {
  76. throw new TlsFatalAlert(AlertDescription.certificate_unknown, e);
  77. }
  78. TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyAgreement);
  79. }
  80. else
  81. {
  82. if (!mTlsSigner.IsValidPublicKey(this.mServerPublicKey))
  83. {
  84. throw new TlsFatalAlert(AlertDescription.certificate_unknown);
  85. }
  86. TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature);
  87. }
  88. base.ProcessServerCertificate(serverCertificate);
  89. }
  90. public override bool RequiresServerKeyExchange
  91. {
  92. get
  93. {
  94. switch (mKeyExchange)
  95. {
  96. case KeyExchangeAlgorithm.DHE_DSS:
  97. case KeyExchangeAlgorithm.DHE_RSA:
  98. case KeyExchangeAlgorithm.DH_anon:
  99. return true;
  100. default:
  101. return false;
  102. }
  103. }
  104. }
  105. public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
  106. {
  107. byte[] types = certificateRequest.CertificateTypes;
  108. for (int i = 0; i < types.Length; ++i)
  109. {
  110. switch (types[i])
  111. {
  112. case ClientCertificateType.rsa_sign:
  113. case ClientCertificateType.dss_sign:
  114. case ClientCertificateType.rsa_fixed_dh:
  115. case ClientCertificateType.dss_fixed_dh:
  116. case ClientCertificateType.ecdsa_sign:
  117. break;
  118. default:
  119. throw new TlsFatalAlert(AlertDescription.illegal_parameter);
  120. }
  121. }
  122. }
  123. public override void ProcessClientCredentials(TlsCredentials clientCredentials)
  124. {
  125. if (clientCredentials is TlsAgreementCredentials)
  126. {
  127. // TODO Validate client cert has matching parameters (see 'areCompatibleParameters')?
  128. this.mAgreementCredentials = (TlsAgreementCredentials)clientCredentials;
  129. }
  130. else if (clientCredentials is TlsSignerCredentials)
  131. {
  132. // OK
  133. }
  134. else
  135. {
  136. throw new TlsFatalAlert(AlertDescription.internal_error);
  137. }
  138. }
  139. public override void GenerateClientKeyExchange(Stream output)
  140. {
  141. /*
  142. * RFC 2246 7.4.7.2 If the client certificate already contains a suitable Diffie-Hellman
  143. * key, then Yc is implicit and does not need to be sent again. In this case, the Client Key
  144. * Exchange message will be sent, but will be empty.
  145. */
  146. if (mAgreementCredentials == null)
  147. {
  148. this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom,
  149. mDHParameters, output);
  150. }
  151. }
  152. public override void ProcessClientCertificate(Certificate clientCertificate)
  153. {
  154. // TODO Extract the public key and validate
  155. /*
  156. * TODO If the certificate is 'fixed', take the public key as dhAgreePublicKey and check
  157. * that the parameters match the server's (see 'areCompatibleParameters').
  158. */
  159. }
  160. public override void ProcessClientKeyExchange(Stream input)
  161. {
  162. if (mDHAgreePublicKey != null)
  163. {
  164. // For dss_fixed_dh and rsa_fixed_dh, the key arrived in the client certificate
  165. return;
  166. }
  167. BigInteger Yc = TlsDHUtilities.ReadDHParameter(input);
  168. this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters));
  169. }
  170. public override byte[] GeneratePremasterSecret()
  171. {
  172. if (mAgreementCredentials != null)
  173. {
  174. return mAgreementCredentials.GenerateAgreement(mDHAgreePublicKey);
  175. }
  176. if (mDHAgreePrivateKey != null)
  177. {
  178. return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreePublicKey, mDHAgreePrivateKey);
  179. }
  180. throw new TlsFatalAlert(AlertDescription.internal_error);
  181. }
  182. protected virtual int MinimumPrimeBits
  183. {
  184. get { return 1024; }
  185. }
  186. protected virtual DHParameters ValidateDHParameters(DHParameters parameters)
  187. {
  188. if (parameters.P.BitLength < MinimumPrimeBits)
  189. throw new TlsFatalAlert(AlertDescription.insufficient_security);
  190. return TlsDHUtilities.ValidateDHParameters(parameters);
  191. }
  192. }
  193. }
  194. #endif