123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- using System;
- using System.Collections;
- using System.IO;
- using Org.BouncyCastle.Asn1.X509;
- using Org.BouncyCastle.Crypto.Parameters;
- using Org.BouncyCastle.Math;
- using Org.BouncyCastle.Security;
- namespace Org.BouncyCastle.Crypto.Tls
- {
- /// <summary>(D)TLS DH key exchange.</summary>
- public class TlsDHKeyExchange
- : AbstractTlsKeyExchange
- {
- protected TlsSigner mTlsSigner;
- protected DHParameters mDHParameters;
- protected AsymmetricKeyParameter mServerPublicKey;
- protected TlsAgreementCredentials mAgreementCredentials;
- protected DHPrivateKeyParameters mDHAgreePrivateKey;
- protected DHPublicKeyParameters mDHAgreePublicKey;
- public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
- : base(keyExchange, supportedSignatureAlgorithms)
- {
- switch (keyExchange)
- {
- case KeyExchangeAlgorithm.DH_RSA:
- case KeyExchangeAlgorithm.DH_DSS:
- this.mTlsSigner = null;
- break;
- case KeyExchangeAlgorithm.DHE_RSA:
- this.mTlsSigner = new TlsRsaSigner();
- break;
- case KeyExchangeAlgorithm.DHE_DSS:
- this.mTlsSigner = new TlsDssSigner();
- break;
- default:
- throw new InvalidOperationException("unsupported key exchange algorithm");
- }
- this.mDHParameters = dhParameters;
- }
- public override void Init(TlsContext context)
- {
- base.Init(context);
- if (this.mTlsSigner != null)
- {
- this.mTlsSigner.Init(context);
- }
- }
- public override void SkipServerCredentials()
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- public override void ProcessServerCertificate(Certificate serverCertificate)
- {
- if (serverCertificate.IsEmpty)
- throw new TlsFatalAlert(AlertDescription.bad_certificate);
- X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
- SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
- try
- {
- this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo);
- }
- catch (Exception e)
- {
- throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e);
- }
- if (mTlsSigner == null)
- {
- try
- {
- this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey);
- this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
- }
- catch (InvalidCastException e)
- {
- throw new TlsFatalAlert(AlertDescription.certificate_unknown, e);
- }
- TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyAgreement);
- }
- else
- {
- if (!mTlsSigner.IsValidPublicKey(this.mServerPublicKey))
- {
- throw new TlsFatalAlert(AlertDescription.certificate_unknown);
- }
- TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature);
- }
- base.ProcessServerCertificate(serverCertificate);
- }
- public override bool RequiresServerKeyExchange
- {
- get
- {
- switch (mKeyExchange)
- {
- case KeyExchangeAlgorithm.DHE_DSS:
- case KeyExchangeAlgorithm.DHE_RSA:
- case KeyExchangeAlgorithm.DH_anon:
- return true;
- default:
- return false;
- }
- }
- }
- public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
- {
- byte[] types = certificateRequest.CertificateTypes;
- for (int i = 0; i < types.Length; ++i)
- {
- switch (types[i])
- {
- case ClientCertificateType.rsa_sign:
- case ClientCertificateType.dss_sign:
- case ClientCertificateType.rsa_fixed_dh:
- case ClientCertificateType.dss_fixed_dh:
- case ClientCertificateType.ecdsa_sign:
- break;
- default:
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
- }
- public override void ProcessClientCredentials(TlsCredentials clientCredentials)
- {
- if (clientCredentials is TlsAgreementCredentials)
- {
- // TODO Validate client cert has matching parameters (see 'areCompatibleParameters')?
- this.mAgreementCredentials = (TlsAgreementCredentials)clientCredentials;
- }
- else if (clientCredentials is TlsSignerCredentials)
- {
- // OK
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- }
- public override void GenerateClientKeyExchange(Stream output)
- {
- /*
- * RFC 2246 7.4.7.2 If the client certificate already contains a suitable Diffie-Hellman
- * key, then Yc is implicit and does not need to be sent again. In this case, the Client Key
- * Exchange message will be sent, but will be empty.
- */
- if (mAgreementCredentials == null)
- {
- this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom,
- mDHParameters, output);
- }
- }
- public override void ProcessClientCertificate(Certificate clientCertificate)
- {
- // TODO Extract the public key and validate
- /*
- * TODO If the certificate is 'fixed', take the public key as dhAgreePublicKey and check
- * that the parameters match the server's (see 'areCompatibleParameters').
- */
- }
- public override void ProcessClientKeyExchange(Stream input)
- {
- if (mDHAgreePublicKey != null)
- {
- // For dss_fixed_dh and rsa_fixed_dh, the key arrived in the client certificate
- return;
- }
- BigInteger Yc = TlsDHUtilities.ReadDHParameter(input);
- this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters));
- }
- public override byte[] GeneratePremasterSecret()
- {
- if (mAgreementCredentials != null)
- {
- return mAgreementCredentials.GenerateAgreement(mDHAgreePublicKey);
- }
- if (mDHAgreePrivateKey != null)
- {
- return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreePublicKey, mDHAgreePrivateKey);
- }
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- protected virtual int MinimumPrimeBits
- {
- get { return 1024; }
- }
- protected virtual DHParameters ValidateDHParameters(DHParameters parameters)
- {
- if (parameters.P.BitLength < MinimumPrimeBits)
- throw new TlsFatalAlert(AlertDescription.insufficient_security);
- return TlsDHUtilities.ValidateDHParameters(parameters);
- }
- }
- }
- #endif
|