228 lines
5.2 KiB
C#
228 lines
5.2 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using Org.BouncyCastle.Asn1.X509;
|
|
using Org.BouncyCastle.Crypto.Parameters;
|
|
using Org.BouncyCastle.Security;
|
|
|
|
namespace Org.BouncyCastle.Crypto.Tls;
|
|
|
|
public class TlsDHKeyExchange : AbstractTlsKeyExchange
|
|
{
|
|
protected TlsSigner mTlsSigner;
|
|
|
|
protected TlsDHVerifier mDHVerifier;
|
|
|
|
protected DHParameters mDHParameters;
|
|
|
|
protected AsymmetricKeyParameter mServerPublicKey;
|
|
|
|
protected TlsAgreementCredentials mAgreementCredentials;
|
|
|
|
protected DHPrivateKeyParameters mDHAgreePrivateKey;
|
|
|
|
protected DHPublicKeyParameters mDHAgreePublicKey;
|
|
|
|
public override bool RequiresServerKeyExchange
|
|
{
|
|
get
|
|
{
|
|
switch (mKeyExchange)
|
|
{
|
|
case 3:
|
|
case 5:
|
|
case 11:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
[Obsolete("Use constructor that takes a TlsDHVerifier")]
|
|
public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
|
|
: this(keyExchange, supportedSignatureAlgorithms, new DefaultTlsDHVerifier(), dhParameters)
|
|
{
|
|
}
|
|
|
|
public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters)
|
|
: base(keyExchange, supportedSignatureAlgorithms)
|
|
{
|
|
switch (keyExchange)
|
|
{
|
|
case 7:
|
|
case 9:
|
|
case 11:
|
|
mTlsSigner = null;
|
|
break;
|
|
case 5:
|
|
mTlsSigner = new TlsRsaSigner();
|
|
break;
|
|
case 3:
|
|
mTlsSigner = new TlsDssSigner();
|
|
break;
|
|
default:
|
|
throw new InvalidOperationException("unsupported key exchange algorithm");
|
|
}
|
|
mDHVerifier = dhVerifier;
|
|
mDHParameters = dhParameters;
|
|
}
|
|
|
|
public override void Init(TlsContext context)
|
|
{
|
|
base.Init(context);
|
|
if (mTlsSigner != null)
|
|
{
|
|
mTlsSigner.Init(context);
|
|
}
|
|
}
|
|
|
|
public override void SkipServerCredentials()
|
|
{
|
|
if (mKeyExchange != 11)
|
|
{
|
|
throw new TlsFatalAlert(10);
|
|
}
|
|
}
|
|
|
|
public override void ProcessServerCertificate(Certificate serverCertificate)
|
|
{
|
|
if (mKeyExchange == 11)
|
|
{
|
|
throw new TlsFatalAlert(10);
|
|
}
|
|
if (serverCertificate.IsEmpty)
|
|
{
|
|
throw new TlsFatalAlert(42);
|
|
}
|
|
X509CertificateStructure certificateAt = serverCertificate.GetCertificateAt(0);
|
|
SubjectPublicKeyInfo subjectPublicKeyInfo = certificateAt.SubjectPublicKeyInfo;
|
|
try
|
|
{
|
|
mServerPublicKey = PublicKeyFactory.CreateKey(subjectPublicKeyInfo);
|
|
}
|
|
catch (Exception alertCause)
|
|
{
|
|
throw new TlsFatalAlert(43, alertCause);
|
|
}
|
|
if (mTlsSigner == null)
|
|
{
|
|
try
|
|
{
|
|
mDHAgreePublicKey = (DHPublicKeyParameters)mServerPublicKey;
|
|
mDHParameters = mDHAgreePublicKey.Parameters;
|
|
}
|
|
catch (InvalidCastException alertCause2)
|
|
{
|
|
throw new TlsFatalAlert(46, alertCause2);
|
|
}
|
|
TlsUtilities.ValidateKeyUsage(certificateAt, 8);
|
|
}
|
|
else
|
|
{
|
|
if (!mTlsSigner.IsValidPublicKey(mServerPublicKey))
|
|
{
|
|
throw new TlsFatalAlert(46);
|
|
}
|
|
TlsUtilities.ValidateKeyUsage(certificateAt, 128);
|
|
}
|
|
base.ProcessServerCertificate(serverCertificate);
|
|
}
|
|
|
|
public override byte[] GenerateServerKeyExchange()
|
|
{
|
|
if (!RequiresServerKeyExchange)
|
|
{
|
|
return null;
|
|
}
|
|
MemoryStream memoryStream = new MemoryStream();
|
|
mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom, mDHParameters, memoryStream);
|
|
return memoryStream.ToArray();
|
|
}
|
|
|
|
public override void ProcessServerKeyExchange(Stream input)
|
|
{
|
|
if (!RequiresServerKeyExchange)
|
|
{
|
|
throw new TlsFatalAlert(10);
|
|
}
|
|
mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input);
|
|
mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
|
|
}
|
|
|
|
public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
|
|
{
|
|
if (mKeyExchange == 11)
|
|
{
|
|
throw new TlsFatalAlert(40);
|
|
}
|
|
byte[] certificateTypes = certificateRequest.CertificateTypes;
|
|
for (int i = 0; i < certificateTypes.Length; i++)
|
|
{
|
|
switch (certificateTypes[i])
|
|
{
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 64:
|
|
continue;
|
|
}
|
|
throw new TlsFatalAlert(47);
|
|
}
|
|
}
|
|
|
|
public override void ProcessClientCredentials(TlsCredentials clientCredentials)
|
|
{
|
|
if (mKeyExchange == 11)
|
|
{
|
|
throw new TlsFatalAlert(80);
|
|
}
|
|
if (clientCredentials is TlsAgreementCredentials)
|
|
{
|
|
mAgreementCredentials = (TlsAgreementCredentials)clientCredentials;
|
|
}
|
|
else if (!(clientCredentials is TlsSignerCredentials))
|
|
{
|
|
throw new TlsFatalAlert(80);
|
|
}
|
|
}
|
|
|
|
public override void GenerateClientKeyExchange(Stream output)
|
|
{
|
|
if (mAgreementCredentials == null)
|
|
{
|
|
mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom, mDHParameters, output);
|
|
}
|
|
}
|
|
|
|
public override void ProcessClientCertificate(Certificate clientCertificate)
|
|
{
|
|
if (mKeyExchange == 11)
|
|
{
|
|
throw new TlsFatalAlert(10);
|
|
}
|
|
}
|
|
|
|
public override void ProcessClientKeyExchange(Stream input)
|
|
{
|
|
if (mDHAgreePublicKey == null)
|
|
{
|
|
mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
|
|
}
|
|
}
|
|
|
|
public override byte[] GeneratePremasterSecret()
|
|
{
|
|
if (mAgreementCredentials != null)
|
|
{
|
|
return mAgreementCredentials.GenerateAgreement(mDHAgreePublicKey);
|
|
}
|
|
if (mDHAgreePrivateKey != null)
|
|
{
|
|
return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreePublicKey, mDHAgreePrivateKey);
|
|
}
|
|
throw new TlsFatalAlert(80);
|
|
}
|
|
}
|