| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- using System.Collections;
- using System.IO;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
- namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Tls
- {
- /// <summary>(D)TLS PSK key exchange (RFC 4279).</summary>
- public class TlsPskKeyExchange
- : AbstractTlsKeyExchange
- {
- protected TlsPskIdentity mPskIdentity;
- protected TlsPskIdentityManager mPskIdentityManager;
- protected TlsDHVerifier mDHVerifier;
- protected DHParameters mDHParameters;
- protected int[] mNamedCurves;
- protected byte[] mClientECPointFormats, mServerECPointFormats;
- protected byte[] mPskIdentityHint = null;
- protected byte[] mPsk = null;
- protected DHPrivateKeyParameters mDHAgreePrivateKey = null;
- protected DHPublicKeyParameters mDHAgreePublicKey = null;
- protected ECPrivateKeyParameters mECAgreePrivateKey = null;
- protected ECPublicKeyParameters mECAgreePublicKey = null;
- protected AsymmetricKeyParameter mServerPublicKey = null;
- protected RsaKeyParameters mRsaServerPublicKey = null;
- protected TlsEncryptionCredentials mServerCredentials = null;
- protected byte[] mPremasterSecret;
- [Obsolete("Use constructor that takes a TlsDHVerifier")]
- public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity,
- TlsPskIdentityManager pskIdentityManager, DHParameters dhParameters, int[] namedCurves,
- byte[] clientECPointFormats, byte[] serverECPointFormats)
- : this(keyExchange, supportedSignatureAlgorithms, pskIdentity, pskIdentityManager, new DefaultTlsDHVerifier(),
- dhParameters, namedCurves, clientECPointFormats, serverECPointFormats)
- {
- }
- public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity,
- TlsPskIdentityManager pskIdentityManager, TlsDHVerifier dhVerifier, DHParameters dhParameters, int[] namedCurves,
- byte[] clientECPointFormats, byte[] serverECPointFormats)
- : base(keyExchange, supportedSignatureAlgorithms)
- {
- switch (keyExchange)
- {
- case KeyExchangeAlgorithm.DHE_PSK:
- case KeyExchangeAlgorithm.ECDHE_PSK:
- case KeyExchangeAlgorithm.PSK:
- case KeyExchangeAlgorithm.RSA_PSK:
- break;
- default:
- throw new InvalidOperationException("unsupported key exchange algorithm");
- }
- this.mPskIdentity = pskIdentity;
- this.mPskIdentityManager = pskIdentityManager;
- this.mDHVerifier = dhVerifier;
- this.mDHParameters = dhParameters;
- this.mNamedCurves = namedCurves;
- this.mClientECPointFormats = clientECPointFormats;
- this.mServerECPointFormats = serverECPointFormats;
- }
- public override void SkipServerCredentials()
- {
- if (mKeyExchange == KeyExchangeAlgorithm.RSA_PSK)
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- public override void ProcessServerCredentials(TlsCredentials serverCredentials)
- {
- if (!(serverCredentials is TlsEncryptionCredentials))
- throw new TlsFatalAlert(AlertDescription.internal_error);
- ProcessServerCertificate(serverCredentials.Certificate);
- this.mServerCredentials = (TlsEncryptionCredentials)serverCredentials;
- }
- public override byte[] GenerateServerKeyExchange()
- {
- this.mPskIdentityHint = mPskIdentityManager.GetHint();
- if (this.mPskIdentityHint == null && !RequiresServerKeyExchange)
- return null;
- MemoryStream buf = new MemoryStream();
- if (this.mPskIdentityHint == null)
- {
- TlsUtilities.WriteOpaque16(TlsUtilities.EmptyBytes, buf);
- }
- else
- {
- TlsUtilities.WriteOpaque16(this.mPskIdentityHint, buf);
- }
- if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
- {
- if (this.mDHParameters == null)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom,
- this.mDHParameters, buf);
- }
- else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
- {
- this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom,
- mNamedCurves, mClientECPointFormats, buf);
- }
- return buf.ToArray();
- }
- public override void ProcessServerCertificate(Certificate serverCertificate)
- {
- if (mKeyExchange != KeyExchangeAlgorithm.RSA_PSK)
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- 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);
- }
- // Sanity check the PublicKeyFactory
- if (this.mServerPublicKey.IsPrivate)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- this.mRsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.mServerPublicKey);
- TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment);
- base.ProcessServerCertificate(serverCertificate);
- }
- public override bool RequiresServerKeyExchange
- {
- get
- {
- switch (mKeyExchange)
- {
- case KeyExchangeAlgorithm.DHE_PSK:
- case KeyExchangeAlgorithm.ECDHE_PSK:
- return true;
- default:
- return false;
- }
- }
- }
- public override void ProcessServerKeyExchange(Stream input)
- {
- this.mPskIdentityHint = TlsUtilities.ReadOpaque16(input);
- if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
- {
- this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input);
- this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
- }
- else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
- {
- ECDomainParameters ecParams = TlsEccUtilities.ReadECParameters(mNamedCurves, mClientECPointFormats, input);
- byte[] point = TlsUtilities.ReadOpaque8(input);
- this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey(
- mClientECPointFormats, ecParams, point));
- }
- }
- public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
- public override void ProcessClientCredentials(TlsCredentials clientCredentials)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- public override void GenerateClientKeyExchange(Stream output)
- {
- if (mPskIdentityHint == null)
- {
- mPskIdentity.SkipIdentityHint();
- }
- else
- {
- mPskIdentity.NotifyIdentityHint(mPskIdentityHint);
- }
- byte[] psk_identity = mPskIdentity.GetPskIdentity();
- if (psk_identity == null)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- this.mPsk = mPskIdentity.GetPsk();
- if (mPsk == null)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- TlsUtilities.WriteOpaque16(psk_identity, output);
- mContext.SecurityParameters.pskIdentity = psk_identity;
- if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
- {
- this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom,
- mDHParameters, output);
- }
- else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
- {
- this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom,
- mServerECPointFormats, mECAgreePublicKey.Parameters, output);
- }
- else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK)
- {
- this.mPremasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(mContext,
- this.mRsaServerPublicKey, output);
- }
- }
- public override void ProcessClientKeyExchange(Stream input)
- {
- byte[] psk_identity = TlsUtilities.ReadOpaque16(input);
- this.mPsk = mPskIdentityManager.GetPsk(psk_identity);
- if (mPsk == null)
- throw new TlsFatalAlert(AlertDescription.unknown_psk_identity);
- mContext.SecurityParameters.pskIdentity = psk_identity;
- if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
- {
- this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
- }
- else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
- {
- byte[] point = TlsUtilities.ReadOpaque8(input);
- ECDomainParameters curve_params = this.mECAgreePrivateKey.Parameters;
- this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey(
- mServerECPointFormats, curve_params, point));
- }
- else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK)
- {
- byte[] encryptedPreMasterSecret;
- if (TlsUtilities.IsSsl(mContext))
- {
- // TODO Do any SSLv3 clients actually include the length?
- encryptedPreMasterSecret = Streams.ReadAll(input);
- }
- else
- {
- encryptedPreMasterSecret = TlsUtilities.ReadOpaque16(input);
- }
- this.mPremasterSecret = mServerCredentials.DecryptPreMasterSecret(encryptedPreMasterSecret);
- }
- }
- public override byte[] GeneratePremasterSecret()
- {
- byte[] other_secret = GenerateOtherSecret(mPsk.Length);
- MemoryStream buf = new MemoryStream(4 + other_secret.Length + mPsk.Length);
- TlsUtilities.WriteOpaque16(other_secret, buf);
- TlsUtilities.WriteOpaque16(mPsk, buf);
- Arrays.Fill(mPsk, (byte)0);
- this.mPsk = null;
- return buf.ToArray();
- }
- protected virtual byte[] GenerateOtherSecret(int pskLength)
- {
- if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
- {
- if (mDHAgreePrivateKey != null)
- {
- return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreePublicKey, mDHAgreePrivateKey);
- }
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
- {
- if (mECAgreePrivateKey != null)
- {
- return TlsEccUtilities.CalculateECDHBasicAgreement(mECAgreePublicKey, mECAgreePrivateKey);
- }
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK)
- {
- return this.mPremasterSecret;
- }
- return new byte[pskLength];
- }
- protected virtual RsaKeyParameters ValidateRsaPublicKey(RsaKeyParameters key)
- {
- // TODO What is the minimum bit length required?
- // key.Modulus.BitLength;
- if (!key.Exponent.IsProbablePrime(2))
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- return key;
- }
- }
- }
- #pragma warning restore
- #endif
|