init commit
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AbstractTlsAgreementCredentials : AbstractTlsCredentials, TlsAgreementCredentials, TlsCredentials
|
||||
{
|
||||
public abstract byte[] GenerateAgreement(AsymmetricKeyParameter peerPublicKey);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class AbstractTlsCipherFactory : TlsCipherFactory
|
||||
{
|
||||
public virtual TlsCipher CreateCipher(TlsContext context, int encryptionAlgorithm, int macAlgorithm)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AbstractTlsClient : AbstractTlsPeer, TlsClient, TlsPeer
|
||||
{
|
||||
protected TlsCipherFactory mCipherFactory;
|
||||
|
||||
protected TlsClientContext mContext;
|
||||
|
||||
protected IList mSupportedSignatureAlgorithms;
|
||||
|
||||
protected int[] mNamedCurves;
|
||||
|
||||
protected byte[] mClientECPointFormats;
|
||||
|
||||
protected byte[] mServerECPointFormats;
|
||||
|
||||
protected int mSelectedCipherSuite;
|
||||
|
||||
protected short mSelectedCompressionMethod;
|
||||
|
||||
public virtual ProtocolVersion ClientHelloRecordLayerVersion => ClientVersion;
|
||||
|
||||
public virtual ProtocolVersion ClientVersion => ProtocolVersion.TLSv12;
|
||||
|
||||
public virtual bool IsFallback => false;
|
||||
|
||||
public virtual ProtocolVersion MinimumVersion => ProtocolVersion.TLSv10;
|
||||
|
||||
public AbstractTlsClient()
|
||||
: this(new DefaultTlsCipherFactory())
|
||||
{
|
||||
}
|
||||
|
||||
public AbstractTlsClient(TlsCipherFactory cipherFactory)
|
||||
{
|
||||
mCipherFactory = cipherFactory;
|
||||
}
|
||||
|
||||
protected virtual bool AllowUnexpectedServerExtension(int extensionType, byte[] extensionData)
|
||||
{
|
||||
switch (extensionType)
|
||||
{
|
||||
case 10:
|
||||
TlsEccUtilities.ReadSupportedEllipticCurvesExtension(extensionData);
|
||||
return true;
|
||||
case 11:
|
||||
TlsEccUtilities.ReadSupportedPointFormatsExtension(extensionData);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CheckForUnexpectedServerExtension(IDictionary serverExtensions, int extensionType)
|
||||
{
|
||||
byte[] extensionData = TlsUtilities.GetExtensionData(serverExtensions, extensionType);
|
||||
if (extensionData != null && !AllowUnexpectedServerExtension(extensionType, extensionData))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Init(TlsClientContext context)
|
||||
{
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public virtual TlsSession GetSessionToResume()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual IDictionary GetClientExtensions()
|
||||
{
|
||||
IDictionary dictionary = null;
|
||||
ProtocolVersion clientVersion = mContext.ClientVersion;
|
||||
if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(clientVersion))
|
||||
{
|
||||
mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultSupportedSignatureAlgorithms();
|
||||
dictionary = TlsExtensionsUtilities.EnsureExtensionsInitialised(dictionary);
|
||||
TlsUtilities.AddSignatureAlgorithmsExtension(dictionary, mSupportedSignatureAlgorithms);
|
||||
}
|
||||
if (TlsEccUtilities.ContainsEccCipherSuites(GetCipherSuites()))
|
||||
{
|
||||
mNamedCurves = new int[2] { 23, 24 };
|
||||
mClientECPointFormats = new byte[3] { 0, 1, 2 };
|
||||
dictionary = TlsExtensionsUtilities.EnsureExtensionsInitialised(dictionary);
|
||||
TlsEccUtilities.AddSupportedEllipticCurvesExtension(dictionary, mNamedCurves);
|
||||
TlsEccUtilities.AddSupportedPointFormatsExtension(dictionary, mClientECPointFormats);
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
public virtual void NotifyServerVersion(ProtocolVersion serverVersion)
|
||||
{
|
||||
if (!MinimumVersion.IsEqualOrEarlierVersionOf(serverVersion))
|
||||
{
|
||||
throw new TlsFatalAlert(70);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract int[] GetCipherSuites();
|
||||
|
||||
public virtual byte[] GetCompressionMethods()
|
||||
{
|
||||
return new byte[1];
|
||||
}
|
||||
|
||||
public virtual void NotifySessionID(byte[] sessionID)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void NotifySelectedCipherSuite(int selectedCipherSuite)
|
||||
{
|
||||
mSelectedCipherSuite = selectedCipherSuite;
|
||||
}
|
||||
|
||||
public virtual void NotifySelectedCompressionMethod(byte selectedCompressionMethod)
|
||||
{
|
||||
mSelectedCompressionMethod = selectedCompressionMethod;
|
||||
}
|
||||
|
||||
public virtual void ProcessServerExtensions(IDictionary serverExtensions)
|
||||
{
|
||||
if (serverExtensions != null)
|
||||
{
|
||||
CheckForUnexpectedServerExtension(serverExtensions, 13);
|
||||
CheckForUnexpectedServerExtension(serverExtensions, 10);
|
||||
if (TlsEccUtilities.IsEccCipherSuite(mSelectedCipherSuite))
|
||||
{
|
||||
mServerECPointFormats = TlsEccUtilities.GetSupportedPointFormatsExtension(serverExtensions);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckForUnexpectedServerExtension(serverExtensions, 11);
|
||||
}
|
||||
CheckForUnexpectedServerExtension(serverExtensions, 21);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ProcessServerSupplementalData(IList serverSupplementalData)
|
||||
{
|
||||
if (serverSupplementalData != null)
|
||||
{
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract TlsKeyExchange GetKeyExchange();
|
||||
|
||||
public abstract TlsAuthentication GetAuthentication();
|
||||
|
||||
public virtual IList GetClientSupplementalData()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override TlsCompression GetCompression()
|
||||
{
|
||||
return mSelectedCompressionMethod switch
|
||||
{
|
||||
0 => new TlsNullCompression(),
|
||||
1 => new TlsDeflateCompression(),
|
||||
_ => throw new TlsFatalAlert(80),
|
||||
};
|
||||
}
|
||||
|
||||
public override TlsCipher GetCipher()
|
||||
{
|
||||
int encryptionAlgorithm = TlsUtilities.GetEncryptionAlgorithm(mSelectedCipherSuite);
|
||||
int macAlgorithm = TlsUtilities.GetMacAlgorithm(mSelectedCipherSuite);
|
||||
return mCipherFactory.CreateCipher(mContext, encryptionAlgorithm, macAlgorithm);
|
||||
}
|
||||
|
||||
public virtual void NotifyNewSessionTicket(NewSessionTicket newSessionTicket)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Org.BouncyCastle.Crypto.Prng;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal abstract class AbstractTlsContext : TlsContext
|
||||
{
|
||||
private static long counter = Times.NanoTime();
|
||||
|
||||
private readonly IRandomGenerator mNonceRandom;
|
||||
|
||||
private readonly SecureRandom mSecureRandom;
|
||||
|
||||
private readonly SecurityParameters mSecurityParameters;
|
||||
|
||||
private ProtocolVersion mClientVersion = null;
|
||||
|
||||
private ProtocolVersion mServerVersion = null;
|
||||
|
||||
private TlsSession mSession = null;
|
||||
|
||||
private object mUserObject = null;
|
||||
|
||||
public virtual IRandomGenerator NonceRandomGenerator => mNonceRandom;
|
||||
|
||||
public virtual SecureRandom SecureRandom => mSecureRandom;
|
||||
|
||||
public virtual SecurityParameters SecurityParameters => mSecurityParameters;
|
||||
|
||||
public abstract bool IsServer { get; }
|
||||
|
||||
public virtual ProtocolVersion ClientVersion => mClientVersion;
|
||||
|
||||
public virtual ProtocolVersion ServerVersion => mServerVersion;
|
||||
|
||||
public virtual TlsSession ResumableSession => mSession;
|
||||
|
||||
public virtual object UserObject
|
||||
{
|
||||
get
|
||||
{
|
||||
return mUserObject;
|
||||
}
|
||||
set
|
||||
{
|
||||
mUserObject = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static long NextCounterValue()
|
||||
{
|
||||
return Interlocked.Increment(ref counter);
|
||||
}
|
||||
|
||||
internal AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters)
|
||||
{
|
||||
IDigest digest = TlsUtilities.CreateHash(4);
|
||||
byte[] array = new byte[digest.GetDigestSize()];
|
||||
secureRandom.NextBytes(array);
|
||||
mNonceRandom = new DigestRandomGenerator(digest);
|
||||
mNonceRandom.AddSeedMaterial(NextCounterValue());
|
||||
mNonceRandom.AddSeedMaterial(Times.NanoTime());
|
||||
mNonceRandom.AddSeedMaterial(array);
|
||||
mSecureRandom = secureRandom;
|
||||
mSecurityParameters = securityParameters;
|
||||
}
|
||||
|
||||
internal virtual void SetClientVersion(ProtocolVersion clientVersion)
|
||||
{
|
||||
mClientVersion = clientVersion;
|
||||
}
|
||||
|
||||
internal virtual void SetServerVersion(ProtocolVersion serverVersion)
|
||||
{
|
||||
mServerVersion = serverVersion;
|
||||
}
|
||||
|
||||
internal virtual void SetResumableSession(TlsSession session)
|
||||
{
|
||||
mSession = session;
|
||||
}
|
||||
|
||||
public virtual byte[] ExportKeyingMaterial(string asciiLabel, byte[] context_value, int length)
|
||||
{
|
||||
if (context_value != null && !TlsUtilities.IsValidUint16(context_value.Length))
|
||||
{
|
||||
throw new ArgumentException("must have length less than 2^16 (or be null)", "context_value");
|
||||
}
|
||||
SecurityParameters securityParameters = SecurityParameters;
|
||||
if (!securityParameters.IsExtendedMasterSecret)
|
||||
{
|
||||
throw new InvalidOperationException("cannot export keying material without extended_master_secret");
|
||||
}
|
||||
byte[] clientRandom = securityParameters.ClientRandom;
|
||||
byte[] serverRandom = securityParameters.ServerRandom;
|
||||
int num = clientRandom.Length + serverRandom.Length;
|
||||
if (context_value != null)
|
||||
{
|
||||
num += 2 + context_value.Length;
|
||||
}
|
||||
byte[] array = new byte[num];
|
||||
int num2 = 0;
|
||||
Array.Copy(clientRandom, 0, array, num2, clientRandom.Length);
|
||||
num2 += clientRandom.Length;
|
||||
Array.Copy(serverRandom, 0, array, num2, serverRandom.Length);
|
||||
num2 += serverRandom.Length;
|
||||
if (context_value != null)
|
||||
{
|
||||
TlsUtilities.WriteUint16(context_value.Length, array, num2);
|
||||
num2 += 2;
|
||||
Array.Copy(context_value, 0, array, num2, context_value.Length);
|
||||
num2 += context_value.Length;
|
||||
}
|
||||
if (num2 != num)
|
||||
{
|
||||
throw new InvalidOperationException("error in calculation of seed for export");
|
||||
}
|
||||
return TlsUtilities.PRF(this, securityParameters.MasterSecret, asciiLabel, array, length);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AbstractTlsCredentials : TlsCredentials
|
||||
{
|
||||
public abstract Certificate Certificate { get; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AbstractTlsEncryptionCredentials : AbstractTlsCredentials, TlsEncryptionCredentials, TlsCredentials
|
||||
{
|
||||
public abstract byte[] DecryptPreMasterSecret(byte[] encryptedPreMasterSecret);
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AbstractTlsKeyExchange : TlsKeyExchange
|
||||
{
|
||||
protected readonly int mKeyExchange;
|
||||
|
||||
protected IList mSupportedSignatureAlgorithms;
|
||||
|
||||
protected TlsContext mContext;
|
||||
|
||||
public virtual bool RequiresServerKeyExchange => false;
|
||||
|
||||
protected AbstractTlsKeyExchange(int keyExchange, IList supportedSignatureAlgorithms)
|
||||
{
|
||||
mKeyExchange = keyExchange;
|
||||
mSupportedSignatureAlgorithms = supportedSignatureAlgorithms;
|
||||
}
|
||||
|
||||
protected virtual DigitallySigned ParseSignature(Stream input)
|
||||
{
|
||||
DigitallySigned digitallySigned = DigitallySigned.Parse(mContext, input);
|
||||
SignatureAndHashAlgorithm algorithm = digitallySigned.Algorithm;
|
||||
if (algorithm != null)
|
||||
{
|
||||
TlsUtilities.VerifySupportedSignatureAlgorithm(mSupportedSignatureAlgorithms, algorithm);
|
||||
}
|
||||
return digitallySigned;
|
||||
}
|
||||
|
||||
public virtual void Init(TlsContext context)
|
||||
{
|
||||
mContext = context;
|
||||
ProtocolVersion clientVersion = context.ClientVersion;
|
||||
if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(clientVersion))
|
||||
{
|
||||
if (mSupportedSignatureAlgorithms == null)
|
||||
{
|
||||
switch (mKeyExchange)
|
||||
{
|
||||
case 3:
|
||||
case 7:
|
||||
case 22:
|
||||
mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultDssSignatureAlgorithms();
|
||||
break;
|
||||
case 16:
|
||||
case 17:
|
||||
mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultECDsaSignatureAlgorithms();
|
||||
break;
|
||||
case 1:
|
||||
case 5:
|
||||
case 9:
|
||||
case 15:
|
||||
case 18:
|
||||
case 19:
|
||||
case 23:
|
||||
mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultRsaSignatureAlgorithms();
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("unsupported key exchange algorithm");
|
||||
case 13:
|
||||
case 14:
|
||||
case 21:
|
||||
case 24:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mSupportedSignatureAlgorithms != null)
|
||||
{
|
||||
throw new InvalidOperationException("supported_signature_algorithms not allowed for " + clientVersion);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void SkipServerCredentials();
|
||||
|
||||
public virtual void ProcessServerCertificate(Certificate serverCertificate)
|
||||
{
|
||||
if (mSupportedSignatureAlgorithms != null)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ProcessServerCredentials(TlsCredentials serverCredentials)
|
||||
{
|
||||
ProcessServerCertificate(serverCredentials.Certificate);
|
||||
}
|
||||
|
||||
public virtual byte[] GenerateServerKeyExchange()
|
||||
{
|
||||
if (RequiresServerKeyExchange)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual void SkipServerKeyExchange()
|
||||
{
|
||||
if (RequiresServerKeyExchange)
|
||||
{
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ProcessServerKeyExchange(Stream input)
|
||||
{
|
||||
if (!RequiresServerKeyExchange)
|
||||
{
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void ValidateCertificateRequest(CertificateRequest certificateRequest);
|
||||
|
||||
public virtual void SkipClientCredentials()
|
||||
{
|
||||
}
|
||||
|
||||
public abstract void ProcessClientCredentials(TlsCredentials clientCredentials);
|
||||
|
||||
public virtual void ProcessClientCertificate(Certificate clientCertificate)
|
||||
{
|
||||
}
|
||||
|
||||
public abstract void GenerateClientKeyExchange(Stream output);
|
||||
|
||||
public virtual void ProcessClientKeyExchange(Stream input)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
public abstract byte[] GeneratePremasterSecret();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AbstractTlsPeer : TlsPeer
|
||||
{
|
||||
public virtual bool RequiresExtendedMasterSecret()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool ShouldUseGmtUnixTime()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void NotifySecureRenegotiation(bool secureRenegotiation)
|
||||
{
|
||||
if (!secureRenegotiation)
|
||||
{
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract TlsCompression GetCompression();
|
||||
|
||||
public abstract TlsCipher GetCipher();
|
||||
|
||||
public virtual void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void NotifyAlertReceived(byte alertLevel, byte alertDescription)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void NotifyHandshakeComplete()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
using System.Collections;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AbstractTlsServer : AbstractTlsPeer, TlsServer, TlsPeer
|
||||
{
|
||||
protected TlsCipherFactory mCipherFactory;
|
||||
|
||||
protected TlsServerContext mContext;
|
||||
|
||||
protected ProtocolVersion mClientVersion;
|
||||
|
||||
protected int[] mOfferedCipherSuites;
|
||||
|
||||
protected byte[] mOfferedCompressionMethods;
|
||||
|
||||
protected IDictionary mClientExtensions;
|
||||
|
||||
protected bool mEncryptThenMacOffered;
|
||||
|
||||
protected short mMaxFragmentLengthOffered;
|
||||
|
||||
protected bool mTruncatedHMacOffered;
|
||||
|
||||
protected IList mSupportedSignatureAlgorithms;
|
||||
|
||||
protected bool mEccCipherSuitesOffered;
|
||||
|
||||
protected int[] mNamedCurves;
|
||||
|
||||
protected byte[] mClientECPointFormats;
|
||||
|
||||
protected byte[] mServerECPointFormats;
|
||||
|
||||
protected ProtocolVersion mServerVersion;
|
||||
|
||||
protected int mSelectedCipherSuite;
|
||||
|
||||
protected byte mSelectedCompressionMethod;
|
||||
|
||||
protected IDictionary mServerExtensions;
|
||||
|
||||
protected virtual bool AllowEncryptThenMac => true;
|
||||
|
||||
protected virtual bool AllowTruncatedHMac => false;
|
||||
|
||||
protected virtual ProtocolVersion MaximumVersion => ProtocolVersion.TLSv11;
|
||||
|
||||
protected virtual ProtocolVersion MinimumVersion => ProtocolVersion.TLSv10;
|
||||
|
||||
public AbstractTlsServer()
|
||||
: this(new DefaultTlsCipherFactory())
|
||||
{
|
||||
}
|
||||
|
||||
public AbstractTlsServer(TlsCipherFactory cipherFactory)
|
||||
{
|
||||
mCipherFactory = cipherFactory;
|
||||
}
|
||||
|
||||
protected virtual IDictionary CheckServerExtensions()
|
||||
{
|
||||
return mServerExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(mServerExtensions);
|
||||
}
|
||||
|
||||
protected abstract int[] GetCipherSuites();
|
||||
|
||||
protected byte[] GetCompressionMethods()
|
||||
{
|
||||
return new byte[1];
|
||||
}
|
||||
|
||||
protected virtual bool SupportsClientEccCapabilities(int[] namedCurves, byte[] ecPointFormats)
|
||||
{
|
||||
if (namedCurves == null)
|
||||
{
|
||||
return TlsEccUtilities.HasAnySupportedNamedCurves();
|
||||
}
|
||||
foreach (int namedCurve in namedCurves)
|
||||
{
|
||||
if (NamedCurve.IsValid(namedCurve) && (!NamedCurve.RefersToASpecificNamedCurve(namedCurve) || TlsEccUtilities.IsSupportedNamedCurve(namedCurve)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void Init(TlsServerContext context)
|
||||
{
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public virtual void NotifyClientVersion(ProtocolVersion clientVersion)
|
||||
{
|
||||
mClientVersion = clientVersion;
|
||||
}
|
||||
|
||||
public virtual void NotifyFallback(bool isFallback)
|
||||
{
|
||||
if (isFallback && MaximumVersion.IsLaterVersionOf(mClientVersion))
|
||||
{
|
||||
throw new TlsFatalAlert(86);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void NotifyOfferedCipherSuites(int[] offeredCipherSuites)
|
||||
{
|
||||
mOfferedCipherSuites = offeredCipherSuites;
|
||||
mEccCipherSuitesOffered = TlsEccUtilities.ContainsEccCipherSuites(mOfferedCipherSuites);
|
||||
}
|
||||
|
||||
public virtual void NotifyOfferedCompressionMethods(byte[] offeredCompressionMethods)
|
||||
{
|
||||
mOfferedCompressionMethods = offeredCompressionMethods;
|
||||
}
|
||||
|
||||
public virtual void ProcessClientExtensions(IDictionary clientExtensions)
|
||||
{
|
||||
mClientExtensions = clientExtensions;
|
||||
if (clientExtensions != null)
|
||||
{
|
||||
mEncryptThenMacOffered = TlsExtensionsUtilities.HasEncryptThenMacExtension(clientExtensions);
|
||||
mMaxFragmentLengthOffered = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions);
|
||||
if (mMaxFragmentLengthOffered >= 0 && !MaxFragmentLength.IsValid((byte)mMaxFragmentLengthOffered))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
mTruncatedHMacOffered = TlsExtensionsUtilities.HasTruncatedHMacExtension(clientExtensions);
|
||||
mSupportedSignatureAlgorithms = TlsUtilities.GetSignatureAlgorithmsExtension(clientExtensions);
|
||||
if (mSupportedSignatureAlgorithms != null && !TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mClientVersion))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
mNamedCurves = TlsEccUtilities.GetSupportedEllipticCurvesExtension(clientExtensions);
|
||||
mClientECPointFormats = TlsEccUtilities.GetSupportedPointFormatsExtension(clientExtensions);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual ProtocolVersion GetServerVersion()
|
||||
{
|
||||
if (MinimumVersion.IsEqualOrEarlierVersionOf(mClientVersion))
|
||||
{
|
||||
ProtocolVersion maximumVersion = MaximumVersion;
|
||||
if (mClientVersion.IsEqualOrEarlierVersionOf(maximumVersion))
|
||||
{
|
||||
return mServerVersion = mClientVersion;
|
||||
}
|
||||
if (mClientVersion.IsLaterVersionOf(maximumVersion))
|
||||
{
|
||||
return mServerVersion = maximumVersion;
|
||||
}
|
||||
}
|
||||
throw new TlsFatalAlert(70);
|
||||
}
|
||||
|
||||
public virtual int GetSelectedCipherSuite()
|
||||
{
|
||||
IList usableSignatureAlgorithms = TlsUtilities.GetUsableSignatureAlgorithms(mSupportedSignatureAlgorithms);
|
||||
bool flag = SupportsClientEccCapabilities(mNamedCurves, mClientECPointFormats);
|
||||
int[] cipherSuites = GetCipherSuites();
|
||||
foreach (int num in cipherSuites)
|
||||
{
|
||||
if (Arrays.Contains(mOfferedCipherSuites, num) && (flag || !TlsEccUtilities.IsEccCipherSuite(num)) && TlsUtilities.IsValidCipherSuiteForVersion(num, mServerVersion) && TlsUtilities.IsValidCipherSuiteForSignatureAlgorithms(num, usableSignatureAlgorithms))
|
||||
{
|
||||
return mSelectedCipherSuite = num;
|
||||
}
|
||||
}
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
|
||||
public virtual byte GetSelectedCompressionMethod()
|
||||
{
|
||||
byte[] compressionMethods = GetCompressionMethods();
|
||||
for (int i = 0; i < compressionMethods.Length; i++)
|
||||
{
|
||||
if (Arrays.Contains(mOfferedCompressionMethods, compressionMethods[i]))
|
||||
{
|
||||
return mSelectedCompressionMethod = compressionMethods[i];
|
||||
}
|
||||
}
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
|
||||
public virtual IDictionary GetServerExtensions()
|
||||
{
|
||||
if (mEncryptThenMacOffered && AllowEncryptThenMac && TlsUtilities.IsBlockCipherSuite(mSelectedCipherSuite))
|
||||
{
|
||||
TlsExtensionsUtilities.AddEncryptThenMacExtension(CheckServerExtensions());
|
||||
}
|
||||
if (mMaxFragmentLengthOffered >= 0 && TlsUtilities.IsValidUint8(mMaxFragmentLengthOffered) && MaxFragmentLength.IsValid((byte)mMaxFragmentLengthOffered))
|
||||
{
|
||||
TlsExtensionsUtilities.AddMaxFragmentLengthExtension(CheckServerExtensions(), (byte)mMaxFragmentLengthOffered);
|
||||
}
|
||||
if (mTruncatedHMacOffered && AllowTruncatedHMac)
|
||||
{
|
||||
TlsExtensionsUtilities.AddTruncatedHMacExtension(CheckServerExtensions());
|
||||
}
|
||||
if (mClientECPointFormats != null && TlsEccUtilities.IsEccCipherSuite(mSelectedCipherSuite))
|
||||
{
|
||||
mServerECPointFormats = new byte[3] { 0, 1, 2 };
|
||||
TlsEccUtilities.AddSupportedPointFormatsExtension(CheckServerExtensions(), mServerECPointFormats);
|
||||
}
|
||||
return mServerExtensions;
|
||||
}
|
||||
|
||||
public virtual IList GetServerSupplementalData()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract TlsCredentials GetCredentials();
|
||||
|
||||
public virtual CertificateStatus GetCertificateStatus()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract TlsKeyExchange GetKeyExchange();
|
||||
|
||||
public virtual CertificateRequest GetCertificateRequest()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual void ProcessClientSupplementalData(IList clientSupplementalData)
|
||||
{
|
||||
if (clientSupplementalData != null)
|
||||
{
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void NotifyClientCertificate(Certificate clientCertificate)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
public override TlsCompression GetCompression()
|
||||
{
|
||||
if (mSelectedCompressionMethod == 0)
|
||||
{
|
||||
return new TlsNullCompression();
|
||||
}
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
public override TlsCipher GetCipher()
|
||||
{
|
||||
int encryptionAlgorithm = TlsUtilities.GetEncryptionAlgorithm(mSelectedCipherSuite);
|
||||
int macAlgorithm = TlsUtilities.GetMacAlgorithm(mSelectedCipherSuite);
|
||||
return mCipherFactory.CreateCipher(mContext, encryptionAlgorithm, macAlgorithm);
|
||||
}
|
||||
|
||||
public virtual NewSessionTicket GetNewSessionTicket()
|
||||
{
|
||||
return new NewSessionTicket(0L, TlsUtilities.EmptyBytes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AbstractTlsSigner : TlsSigner
|
||||
{
|
||||
protected TlsContext mContext;
|
||||
|
||||
public virtual void Init(TlsContext context)
|
||||
{
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public virtual byte[] GenerateRawSignature(AsymmetricKeyParameter privateKey, byte[] md5AndSha1)
|
||||
{
|
||||
return GenerateRawSignature(null, privateKey, md5AndSha1);
|
||||
}
|
||||
|
||||
public abstract byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey, byte[] hash);
|
||||
|
||||
public virtual bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5AndSha1)
|
||||
{
|
||||
return VerifyRawSignature(null, sigBytes, publicKey, md5AndSha1);
|
||||
}
|
||||
|
||||
public abstract bool VerifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] hash);
|
||||
|
||||
public virtual ISigner CreateSigner(AsymmetricKeyParameter privateKey)
|
||||
{
|
||||
return CreateSigner(null, privateKey);
|
||||
}
|
||||
|
||||
public abstract ISigner CreateSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey);
|
||||
|
||||
public virtual ISigner CreateVerifyer(AsymmetricKeyParameter publicKey)
|
||||
{
|
||||
return CreateVerifyer(null, publicKey);
|
||||
}
|
||||
|
||||
public abstract ISigner CreateVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey);
|
||||
|
||||
public abstract bool IsValidPublicKey(AsymmetricKeyParameter publicKey);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AbstractTlsSignerCredentials : AbstractTlsCredentials, TlsSignerCredentials, TlsCredentials
|
||||
{
|
||||
public virtual SignatureAndHashAlgorithm SignatureAndHashAlgorithm
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new InvalidOperationException("TlsSignerCredentials implementation does not support (D)TLS 1.2+");
|
||||
}
|
||||
}
|
||||
|
||||
public abstract byte[] GenerateCertificateSignature(byte[] hash);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AlertDescription
|
||||
{
|
||||
public const byte close_notify = 0;
|
||||
|
||||
public const byte unexpected_message = 10;
|
||||
|
||||
public const byte bad_record_mac = 20;
|
||||
|
||||
public const byte decryption_failed = 21;
|
||||
|
||||
public const byte record_overflow = 22;
|
||||
|
||||
public const byte decompression_failure = 30;
|
||||
|
||||
public const byte handshake_failure = 40;
|
||||
|
||||
public const byte no_certificate = 41;
|
||||
|
||||
public const byte bad_certificate = 42;
|
||||
|
||||
public const byte unsupported_certificate = 43;
|
||||
|
||||
public const byte certificate_revoked = 44;
|
||||
|
||||
public const byte certificate_expired = 45;
|
||||
|
||||
public const byte certificate_unknown = 46;
|
||||
|
||||
public const byte illegal_parameter = 47;
|
||||
|
||||
public const byte unknown_ca = 48;
|
||||
|
||||
public const byte access_denied = 49;
|
||||
|
||||
public const byte decode_error = 50;
|
||||
|
||||
public const byte decrypt_error = 51;
|
||||
|
||||
public const byte export_restriction = 60;
|
||||
|
||||
public const byte protocol_version = 70;
|
||||
|
||||
public const byte insufficient_security = 71;
|
||||
|
||||
public const byte internal_error = 80;
|
||||
|
||||
public const byte user_canceled = 90;
|
||||
|
||||
public const byte no_renegotiation = 100;
|
||||
|
||||
public const byte unsupported_extension = 110;
|
||||
|
||||
public const byte certificate_unobtainable = 111;
|
||||
|
||||
public const byte unrecognized_name = 112;
|
||||
|
||||
public const byte bad_certificate_status_response = 113;
|
||||
|
||||
public const byte bad_certificate_hash_value = 114;
|
||||
|
||||
public const byte unknown_psk_identity = 115;
|
||||
|
||||
public const byte inappropriate_fallback = 86;
|
||||
|
||||
public static string GetName(byte alertDescription)
|
||||
{
|
||||
return alertDescription switch
|
||||
{
|
||||
0 => "close_notify",
|
||||
10 => "unexpected_message",
|
||||
20 => "bad_record_mac",
|
||||
21 => "decryption_failed",
|
||||
22 => "record_overflow",
|
||||
30 => "decompression_failure",
|
||||
40 => "handshake_failure",
|
||||
41 => "no_certificate",
|
||||
42 => "bad_certificate",
|
||||
43 => "unsupported_certificate",
|
||||
44 => "certificate_revoked",
|
||||
45 => "certificate_expired",
|
||||
46 => "certificate_unknown",
|
||||
47 => "illegal_parameter",
|
||||
48 => "unknown_ca",
|
||||
49 => "access_denied",
|
||||
50 => "decode_error",
|
||||
51 => "decrypt_error",
|
||||
60 => "export_restriction",
|
||||
70 => "protocol_version",
|
||||
71 => "insufficient_security",
|
||||
80 => "internal_error",
|
||||
90 => "user_canceled",
|
||||
100 => "no_renegotiation",
|
||||
110 => "unsupported_extension",
|
||||
111 => "certificate_unobtainable",
|
||||
112 => "unrecognized_name",
|
||||
113 => "bad_certificate_status_response",
|
||||
114 => "bad_certificate_hash_value",
|
||||
115 => "unknown_psk_identity",
|
||||
86 => "inappropriate_fallback",
|
||||
_ => "UNKNOWN",
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetText(byte alertDescription)
|
||||
{
|
||||
return GetName(alertDescription) + "(" + alertDescription + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class AlertLevel
|
||||
{
|
||||
public const byte warning = 1;
|
||||
|
||||
public const byte fatal = 2;
|
||||
|
||||
public static string GetName(byte alertDescription)
|
||||
{
|
||||
return alertDescription switch
|
||||
{
|
||||
1 => "warning",
|
||||
2 => "fatal",
|
||||
_ => "UNKNOWN",
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetText(byte alertDescription)
|
||||
{
|
||||
return GetName(alertDescription) + "(" + alertDescription + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class BasicTlsPskIdentity : TlsPskIdentity
|
||||
{
|
||||
protected byte[] mIdentity;
|
||||
|
||||
protected byte[] mPsk;
|
||||
|
||||
public BasicTlsPskIdentity(byte[] identity, byte[] psk)
|
||||
{
|
||||
mIdentity = Arrays.Clone(identity);
|
||||
mPsk = Arrays.Clone(psk);
|
||||
}
|
||||
|
||||
public BasicTlsPskIdentity(string identity, byte[] psk)
|
||||
{
|
||||
mIdentity = Strings.ToUtf8ByteArray(identity);
|
||||
mPsk = Arrays.Clone(psk);
|
||||
}
|
||||
|
||||
public virtual void SkipIdentityHint()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void NotifyIdentityHint(byte[] psk_identity_hint)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual byte[] GetPskIdentity()
|
||||
{
|
||||
return mIdentity;
|
||||
}
|
||||
|
||||
public virtual byte[] GetPsk()
|
||||
{
|
||||
return mPsk;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class BulkCipherAlgorithm
|
||||
{
|
||||
public const int cls_null = 0;
|
||||
|
||||
public const int rc4 = 1;
|
||||
|
||||
public const int rc2 = 2;
|
||||
|
||||
public const int des = 3;
|
||||
|
||||
public const int cls_3des = 4;
|
||||
|
||||
public const int des40 = 5;
|
||||
|
||||
public const int aes = 6;
|
||||
|
||||
public const int idea = 7;
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class ByteQueue
|
||||
{
|
||||
private const int DefaultCapacity = 1024;
|
||||
|
||||
private byte[] databuf;
|
||||
|
||||
private int skipped = 0;
|
||||
|
||||
private int available = 0;
|
||||
|
||||
private bool readOnlyBuf = false;
|
||||
|
||||
public int Available => available;
|
||||
|
||||
public static int NextTwoPow(int i)
|
||||
{
|
||||
i |= i >> 1;
|
||||
i |= i >> 2;
|
||||
i |= i >> 4;
|
||||
i |= i >> 8;
|
||||
i |= i >> 16;
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
public ByteQueue()
|
||||
: this(1024)
|
||||
{
|
||||
}
|
||||
|
||||
public ByteQueue(int capacity)
|
||||
{
|
||||
databuf = ((capacity == 0) ? TlsUtilities.EmptyBytes : new byte[capacity]);
|
||||
}
|
||||
|
||||
public ByteQueue(byte[] buf, int off, int len)
|
||||
{
|
||||
databuf = buf;
|
||||
skipped = off;
|
||||
available = len;
|
||||
readOnlyBuf = true;
|
||||
}
|
||||
|
||||
public void AddData(byte[] data, int offset, int len)
|
||||
{
|
||||
if (readOnlyBuf)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot add data to read-only buffer");
|
||||
}
|
||||
if (skipped + available + len > databuf.Length)
|
||||
{
|
||||
int num = NextTwoPow(available + len);
|
||||
if (num > databuf.Length)
|
||||
{
|
||||
byte[] destinationArray = new byte[num];
|
||||
Array.Copy(databuf, skipped, destinationArray, 0, available);
|
||||
databuf = destinationArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(databuf, skipped, databuf, 0, available);
|
||||
}
|
||||
skipped = 0;
|
||||
}
|
||||
Array.Copy(data, offset, databuf, skipped + available, len);
|
||||
available += len;
|
||||
}
|
||||
|
||||
public void CopyTo(Stream output, int length)
|
||||
{
|
||||
if (length > available)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot copy " + length + " bytes, only got " + available);
|
||||
}
|
||||
output.Write(databuf, skipped, length);
|
||||
}
|
||||
|
||||
public void Read(byte[] buf, int offset, int len, int skip)
|
||||
{
|
||||
if (buf.Length - offset < len)
|
||||
{
|
||||
throw new ArgumentException("Buffer size of " + buf.Length + " is too small for a read of " + len + " bytes");
|
||||
}
|
||||
if (available - skip < len)
|
||||
{
|
||||
throw new InvalidOperationException("Not enough data to read");
|
||||
}
|
||||
Array.Copy(databuf, skipped + skip, buf, offset, len);
|
||||
}
|
||||
|
||||
public MemoryStream ReadFrom(int length)
|
||||
{
|
||||
if (length > available)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot read " + length + " bytes, only got " + available);
|
||||
}
|
||||
int index = skipped;
|
||||
available -= length;
|
||||
skipped += length;
|
||||
return new MemoryStream(databuf, index, length, writable: false);
|
||||
}
|
||||
|
||||
public void RemoveData(int i)
|
||||
{
|
||||
if (i > available)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot remove " + i + " bytes, only got " + available);
|
||||
}
|
||||
available -= i;
|
||||
skipped += i;
|
||||
}
|
||||
|
||||
public void RemoveData(byte[] buf, int off, int len, int skip)
|
||||
{
|
||||
Read(buf, off, len, skip);
|
||||
RemoveData(skip + len);
|
||||
}
|
||||
|
||||
public byte[] RemoveData(int len, int skip)
|
||||
{
|
||||
byte[] array = new byte[len];
|
||||
RemoveData(array, 0, len, skip);
|
||||
return array;
|
||||
}
|
||||
|
||||
public void Shrink()
|
||||
{
|
||||
if (available == 0)
|
||||
{
|
||||
databuf = TlsUtilities.EmptyBytes;
|
||||
skipped = 0;
|
||||
return;
|
||||
}
|
||||
int num = NextTwoPow(available);
|
||||
if (num < databuf.Length)
|
||||
{
|
||||
byte[] destinationArray = new byte[num];
|
||||
Array.Copy(databuf, skipped, destinationArray, 0, available);
|
||||
databuf = destinationArray;
|
||||
skipped = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class ByteQueueStream : Stream
|
||||
{
|
||||
private readonly ByteQueue buffer;
|
||||
|
||||
public virtual int Available => buffer.Available;
|
||||
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override bool CanWrite => true;
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public ByteQueueStream()
|
||||
{
|
||||
buffer = new ByteQueue();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual int Peek(byte[] buf)
|
||||
{
|
||||
int num = System.Math.Min(buffer.Available, buf.Length);
|
||||
buffer.Read(buf, 0, num, 0);
|
||||
return num;
|
||||
}
|
||||
|
||||
public virtual int Read(byte[] buf)
|
||||
{
|
||||
return Read(buf, 0, buf.Length);
|
||||
}
|
||||
|
||||
public override int Read(byte[] buf, int off, int len)
|
||||
{
|
||||
int num = System.Math.Min(buffer.Available, len);
|
||||
buffer.RemoveData(buf, off, num, 0);
|
||||
return num;
|
||||
}
|
||||
|
||||
public override int ReadByte()
|
||||
{
|
||||
if (buffer.Available == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return buffer.RemoveData(1, 0)[0] & 0xFF;
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public virtual int Skip(int n)
|
||||
{
|
||||
int num = System.Math.Min(buffer.Available, n);
|
||||
buffer.RemoveData(num);
|
||||
return num;
|
||||
}
|
||||
|
||||
public virtual void Write(byte[] buf)
|
||||
{
|
||||
buffer.AddData(buf, 0, buf.Length);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buf, int off, int len)
|
||||
{
|
||||
buffer.AddData(buf, off, len);
|
||||
}
|
||||
|
||||
public override void WriteByte(byte b)
|
||||
{
|
||||
buffer.AddData(new byte[1] { b }, 0, 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class CertChainType
|
||||
{
|
||||
public const byte individual_certs = 0;
|
||||
|
||||
public const byte pkipath = 1;
|
||||
|
||||
public static bool IsValid(byte certChainType)
|
||||
{
|
||||
if (certChainType >= 0)
|
||||
{
|
||||
return certChainType <= 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class Certificate
|
||||
{
|
||||
public static readonly Certificate EmptyChain = new Certificate(new X509CertificateStructure[0]);
|
||||
|
||||
protected readonly X509CertificateStructure[] mCertificateList;
|
||||
|
||||
public virtual int Length => mCertificateList.Length;
|
||||
|
||||
public virtual bool IsEmpty => mCertificateList.Length == 0;
|
||||
|
||||
public Certificate(X509CertificateStructure[] certificateList)
|
||||
{
|
||||
if (certificateList == null)
|
||||
{
|
||||
throw new ArgumentNullException("certificateList");
|
||||
}
|
||||
mCertificateList = certificateList;
|
||||
}
|
||||
|
||||
public virtual X509CertificateStructure[] GetCertificateList()
|
||||
{
|
||||
return CloneCertificateList();
|
||||
}
|
||||
|
||||
public virtual X509CertificateStructure GetCertificateAt(int index)
|
||||
{
|
||||
return mCertificateList[index];
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
IList list = Platform.CreateArrayList(mCertificateList.Length);
|
||||
int num = 0;
|
||||
X509CertificateStructure[] array = mCertificateList;
|
||||
foreach (Asn1Encodable asn1Encodable in array)
|
||||
{
|
||||
byte[] encoded = asn1Encodable.GetEncoded("DER");
|
||||
list.Add(encoded);
|
||||
num += encoded.Length + 3;
|
||||
}
|
||||
TlsUtilities.CheckUint24(num);
|
||||
TlsUtilities.WriteUint24(num, output);
|
||||
foreach (byte[] item in list)
|
||||
{
|
||||
TlsUtilities.WriteOpaque24(item, output);
|
||||
}
|
||||
}
|
||||
|
||||
public static Certificate Parse(Stream input)
|
||||
{
|
||||
int num = TlsUtilities.ReadUint24(input);
|
||||
if (num == 0)
|
||||
{
|
||||
return EmptyChain;
|
||||
}
|
||||
byte[] buffer = TlsUtilities.ReadFully(num, input);
|
||||
MemoryStream memoryStream = new MemoryStream(buffer, writable: false);
|
||||
IList list = Platform.CreateArrayList();
|
||||
while (memoryStream.Position < memoryStream.Length)
|
||||
{
|
||||
byte[] encoding = TlsUtilities.ReadOpaque24(memoryStream);
|
||||
Asn1Object obj = TlsUtilities.ReadAsn1Object(encoding);
|
||||
list.Add(X509CertificateStructure.GetInstance(obj));
|
||||
}
|
||||
X509CertificateStructure[] array = new X509CertificateStructure[list.Count];
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
array[i] = (X509CertificateStructure)list[i];
|
||||
}
|
||||
return new Certificate(array);
|
||||
}
|
||||
|
||||
protected virtual X509CertificateStructure[] CloneCertificateList()
|
||||
{
|
||||
return (X509CertificateStructure[])mCertificateList.Clone();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class CertificateRequest
|
||||
{
|
||||
protected readonly byte[] mCertificateTypes;
|
||||
|
||||
protected readonly IList mSupportedSignatureAlgorithms;
|
||||
|
||||
protected readonly IList mCertificateAuthorities;
|
||||
|
||||
public virtual byte[] CertificateTypes => mCertificateTypes;
|
||||
|
||||
public virtual IList SupportedSignatureAlgorithms => mSupportedSignatureAlgorithms;
|
||||
|
||||
public virtual IList CertificateAuthorities => mCertificateAuthorities;
|
||||
|
||||
public CertificateRequest(byte[] certificateTypes, IList supportedSignatureAlgorithms, IList certificateAuthorities)
|
||||
{
|
||||
mCertificateTypes = certificateTypes;
|
||||
mSupportedSignatureAlgorithms = supportedSignatureAlgorithms;
|
||||
mCertificateAuthorities = certificateAuthorities;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
if (mCertificateTypes == null || mCertificateTypes.Length == 0)
|
||||
{
|
||||
TlsUtilities.WriteUint8(0, output);
|
||||
}
|
||||
else
|
||||
{
|
||||
TlsUtilities.WriteUint8ArrayWithUint8Length(mCertificateTypes, output);
|
||||
}
|
||||
if (mSupportedSignatureAlgorithms != null)
|
||||
{
|
||||
TlsUtilities.EncodeSupportedSignatureAlgorithms(mSupportedSignatureAlgorithms, allowAnonymous: false, output);
|
||||
}
|
||||
if (mCertificateAuthorities == null || mCertificateAuthorities.Count < 1)
|
||||
{
|
||||
TlsUtilities.WriteUint16(0, output);
|
||||
return;
|
||||
}
|
||||
IList list = Platform.CreateArrayList(mCertificateAuthorities.Count);
|
||||
int num = 0;
|
||||
foreach (Asn1Encodable mCertificateAuthority in mCertificateAuthorities)
|
||||
{
|
||||
byte[] encoded = mCertificateAuthority.GetEncoded("DER");
|
||||
list.Add(encoded);
|
||||
num += encoded.Length + 2;
|
||||
}
|
||||
TlsUtilities.CheckUint16(num);
|
||||
TlsUtilities.WriteUint16(num, output);
|
||||
foreach (byte[] item in list)
|
||||
{
|
||||
TlsUtilities.WriteOpaque16(item, output);
|
||||
}
|
||||
}
|
||||
|
||||
public static CertificateRequest Parse(TlsContext context, Stream input)
|
||||
{
|
||||
int num = TlsUtilities.ReadUint8(input);
|
||||
byte[] array = new byte[num];
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
array[i] = TlsUtilities.ReadUint8(input);
|
||||
}
|
||||
IList supportedSignatureAlgorithms = null;
|
||||
if (TlsUtilities.IsTlsV12(context))
|
||||
{
|
||||
supportedSignatureAlgorithms = TlsUtilities.ParseSupportedSignatureAlgorithms(allowAnonymous: false, input);
|
||||
}
|
||||
IList list = Platform.CreateArrayList();
|
||||
byte[] buffer = TlsUtilities.ReadOpaque16(input);
|
||||
MemoryStream memoryStream = new MemoryStream(buffer, writable: false);
|
||||
while (memoryStream.Position < memoryStream.Length)
|
||||
{
|
||||
byte[] encoding = TlsUtilities.ReadOpaque16(memoryStream);
|
||||
Asn1Object obj = TlsUtilities.ReadDerObject(encoding);
|
||||
list.Add(X509Name.GetInstance(obj));
|
||||
}
|
||||
return new CertificateRequest(array, supportedSignatureAlgorithms, list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Asn1.Ocsp;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class CertificateStatus
|
||||
{
|
||||
protected readonly byte mStatusType;
|
||||
|
||||
protected readonly object mResponse;
|
||||
|
||||
public virtual byte StatusType => mStatusType;
|
||||
|
||||
public virtual object Response => mResponse;
|
||||
|
||||
public CertificateStatus(byte statusType, object response)
|
||||
{
|
||||
if (!IsCorrectType(statusType, response))
|
||||
{
|
||||
throw new ArgumentException("not an instance of the correct type", "response");
|
||||
}
|
||||
mStatusType = statusType;
|
||||
mResponse = response;
|
||||
}
|
||||
|
||||
public virtual OcspResponse GetOcspResponse()
|
||||
{
|
||||
if (!IsCorrectType(1, mResponse))
|
||||
{
|
||||
throw new InvalidOperationException("'response' is not an OcspResponse");
|
||||
}
|
||||
return (OcspResponse)mResponse;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
TlsUtilities.WriteUint8(mStatusType, output);
|
||||
byte b = mStatusType;
|
||||
if (b == 1)
|
||||
{
|
||||
byte[] encoded = ((OcspResponse)mResponse).GetEncoded("DER");
|
||||
TlsUtilities.WriteOpaque24(encoded, output);
|
||||
return;
|
||||
}
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
public static CertificateStatus Parse(Stream input)
|
||||
{
|
||||
byte b = TlsUtilities.ReadUint8(input);
|
||||
byte b2 = b;
|
||||
if (b2 == 1)
|
||||
{
|
||||
byte[] encoding = TlsUtilities.ReadOpaque24(input);
|
||||
object instance = OcspResponse.GetInstance(TlsUtilities.ReadDerObject(encoding));
|
||||
return new CertificateStatus(b, instance);
|
||||
}
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
|
||||
protected static bool IsCorrectType(byte statusType, object response)
|
||||
{
|
||||
byte b = statusType;
|
||||
if (b == 1)
|
||||
{
|
||||
return response is OcspResponse;
|
||||
}
|
||||
throw new ArgumentException("unsupported CertificateStatusType", "statusType");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class CertificateStatusRequest
|
||||
{
|
||||
protected readonly byte mStatusType;
|
||||
|
||||
protected readonly object mRequest;
|
||||
|
||||
public virtual byte StatusType => mStatusType;
|
||||
|
||||
public virtual object Request => mRequest;
|
||||
|
||||
public CertificateStatusRequest(byte statusType, object request)
|
||||
{
|
||||
if (!IsCorrectType(statusType, request))
|
||||
{
|
||||
throw new ArgumentException("not an instance of the correct type", "request");
|
||||
}
|
||||
mStatusType = statusType;
|
||||
mRequest = request;
|
||||
}
|
||||
|
||||
public virtual OcspStatusRequest GetOcspStatusRequest()
|
||||
{
|
||||
if (!IsCorrectType(1, mRequest))
|
||||
{
|
||||
throw new InvalidOperationException("'request' is not an OCSPStatusRequest");
|
||||
}
|
||||
return (OcspStatusRequest)mRequest;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
TlsUtilities.WriteUint8(mStatusType, output);
|
||||
byte b = mStatusType;
|
||||
if (b == 1)
|
||||
{
|
||||
((OcspStatusRequest)mRequest).Encode(output);
|
||||
return;
|
||||
}
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
public static CertificateStatusRequest Parse(Stream input)
|
||||
{
|
||||
byte b = TlsUtilities.ReadUint8(input);
|
||||
byte b2 = b;
|
||||
if (b2 == 1)
|
||||
{
|
||||
object request = OcspStatusRequest.Parse(input);
|
||||
return new CertificateStatusRequest(b, request);
|
||||
}
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
|
||||
protected static bool IsCorrectType(byte statusType, object request)
|
||||
{
|
||||
byte b = statusType;
|
||||
if (b == 1)
|
||||
{
|
||||
return request is OcspStatusRequest;
|
||||
}
|
||||
throw new ArgumentException("unsupported CertificateStatusType", "statusType");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class CertificateStatusType
|
||||
{
|
||||
public const byte ocsp = 1;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class CertificateType
|
||||
{
|
||||
public const byte X509 = 0;
|
||||
|
||||
public const byte OpenPGP = 1;
|
||||
|
||||
public const byte RawPublicKey = 2;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class CertificateUrl
|
||||
{
|
||||
internal class ListBuffer16 : MemoryStream
|
||||
{
|
||||
internal ListBuffer16()
|
||||
{
|
||||
TlsUtilities.WriteUint16(0, this);
|
||||
}
|
||||
|
||||
internal void EncodeTo(Stream output)
|
||||
{
|
||||
long num = Length - 2;
|
||||
TlsUtilities.CheckUint16(num);
|
||||
Position = 0L;
|
||||
TlsUtilities.WriteUint16((int)num, this);
|
||||
Streams.WriteBufTo(this, output);
|
||||
Platform.Dispose(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly byte mType;
|
||||
|
||||
protected readonly IList mUrlAndHashList;
|
||||
|
||||
public virtual byte Type => mType;
|
||||
|
||||
public virtual IList UrlAndHashList => mUrlAndHashList;
|
||||
|
||||
public CertificateUrl(byte type, IList urlAndHashList)
|
||||
{
|
||||
if (!CertChainType.IsValid(type))
|
||||
{
|
||||
throw new ArgumentException("not a valid CertChainType value", "type");
|
||||
}
|
||||
if (urlAndHashList == null || urlAndHashList.Count < 1)
|
||||
{
|
||||
throw new ArgumentException("must have length > 0", "urlAndHashList");
|
||||
}
|
||||
mType = type;
|
||||
mUrlAndHashList = urlAndHashList;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
TlsUtilities.WriteUint8(mType, output);
|
||||
ListBuffer16 listBuffer = new ListBuffer16();
|
||||
foreach (UrlAndHash mUrlAndHash in mUrlAndHashList)
|
||||
{
|
||||
mUrlAndHash.Encode(listBuffer);
|
||||
}
|
||||
listBuffer.EncodeTo(output);
|
||||
}
|
||||
|
||||
public static CertificateUrl parse(TlsContext context, Stream input)
|
||||
{
|
||||
byte b = TlsUtilities.ReadUint8(input);
|
||||
if (!CertChainType.IsValid(b))
|
||||
{
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
int num = TlsUtilities.ReadUint16(input);
|
||||
if (num < 1)
|
||||
{
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
byte[] buffer = TlsUtilities.ReadFully(num, input);
|
||||
MemoryStream memoryStream = new MemoryStream(buffer, writable: false);
|
||||
IList list = Platform.CreateArrayList();
|
||||
while (memoryStream.Position < memoryStream.Length)
|
||||
{
|
||||
UrlAndHash value = UrlAndHash.Parse(context, memoryStream);
|
||||
list.Add(value);
|
||||
}
|
||||
return new CertificateUrl(b, list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Macs;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Utilities;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class Chacha20Poly1305 : TlsCipher
|
||||
{
|
||||
private static readonly byte[] Zeroes = new byte[15];
|
||||
|
||||
protected readonly TlsContext context;
|
||||
|
||||
protected readonly ChaCha7539Engine encryptCipher;
|
||||
|
||||
protected readonly ChaCha7539Engine decryptCipher;
|
||||
|
||||
protected readonly byte[] encryptIV;
|
||||
|
||||
protected readonly byte[] decryptIV;
|
||||
|
||||
public Chacha20Poly1305(TlsContext context)
|
||||
{
|
||||
if (!TlsUtilities.IsTlsV12(context))
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
this.context = context;
|
||||
int num = 32;
|
||||
int num2 = 12;
|
||||
int num3 = 2 * num + 2 * num2;
|
||||
byte[] array = TlsUtilities.CalculateKeyBlock(context, num3);
|
||||
int num4 = 0;
|
||||
KeyParameter keyParameter = new KeyParameter(array, num4, num);
|
||||
num4 += num;
|
||||
KeyParameter keyParameter2 = new KeyParameter(array, num4, num);
|
||||
num4 += num;
|
||||
byte[] array2 = Arrays.CopyOfRange(array, num4, num4 + num2);
|
||||
num4 += num2;
|
||||
byte[] array3 = Arrays.CopyOfRange(array, num4, num4 + num2);
|
||||
num4 += num2;
|
||||
if (num4 != num3)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
encryptCipher = new ChaCha7539Engine();
|
||||
decryptCipher = new ChaCha7539Engine();
|
||||
KeyParameter parameters;
|
||||
KeyParameter parameters2;
|
||||
if (context.IsServer)
|
||||
{
|
||||
parameters = keyParameter2;
|
||||
parameters2 = keyParameter;
|
||||
encryptIV = array3;
|
||||
decryptIV = array2;
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters = keyParameter;
|
||||
parameters2 = keyParameter2;
|
||||
encryptIV = array2;
|
||||
decryptIV = array3;
|
||||
}
|
||||
encryptCipher.Init(forEncryption: true, new ParametersWithIV(parameters, encryptIV));
|
||||
decryptCipher.Init(forEncryption: false, new ParametersWithIV(parameters2, decryptIV));
|
||||
}
|
||||
|
||||
public virtual int GetPlaintextLimit(int ciphertextLimit)
|
||||
{
|
||||
return ciphertextLimit - 16;
|
||||
}
|
||||
|
||||
public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
|
||||
{
|
||||
KeyParameter macKey = InitRecord(encryptCipher, forEncryption: true, seqNo, encryptIV);
|
||||
byte[] array = new byte[len + 16];
|
||||
encryptCipher.ProcessBytes(plaintext, offset, len, array, 0);
|
||||
byte[] additionalData = GetAdditionalData(seqNo, type, len);
|
||||
byte[] array2 = CalculateRecordMac(macKey, additionalData, array, 0, len);
|
||||
Array.Copy(array2, 0, array, len, array2.Length);
|
||||
return array;
|
||||
}
|
||||
|
||||
public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
|
||||
{
|
||||
if (GetPlaintextLimit(len) < 0)
|
||||
{
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
KeyParameter macKey = InitRecord(decryptCipher, forEncryption: false, seqNo, decryptIV);
|
||||
int num = len - 16;
|
||||
byte[] additionalData = GetAdditionalData(seqNo, type, num);
|
||||
byte[] a = CalculateRecordMac(macKey, additionalData, ciphertext, offset, num);
|
||||
byte[] b = Arrays.CopyOfRange(ciphertext, offset + num, offset + len);
|
||||
if (!Arrays.ConstantTimeAreEqual(a, b))
|
||||
{
|
||||
throw new TlsFatalAlert(20);
|
||||
}
|
||||
byte[] array = new byte[num];
|
||||
decryptCipher.ProcessBytes(ciphertext, offset, num, array, 0);
|
||||
return array;
|
||||
}
|
||||
|
||||
protected virtual KeyParameter InitRecord(IStreamCipher cipher, bool forEncryption, long seqNo, byte[] iv)
|
||||
{
|
||||
byte[] iv2 = CalculateNonce(seqNo, iv);
|
||||
cipher.Init(forEncryption, new ParametersWithIV(null, iv2));
|
||||
return GenerateRecordMacKey(cipher);
|
||||
}
|
||||
|
||||
protected virtual byte[] CalculateNonce(long seqNo, byte[] iv)
|
||||
{
|
||||
byte[] array = new byte[12];
|
||||
TlsUtilities.WriteUint64(seqNo, array, 4);
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
byte[] array3;
|
||||
byte[] array2 = (array3 = array);
|
||||
int num = i;
|
||||
nint num2 = num;
|
||||
array2[num] = (byte)(array3[num2] ^ iv[i]);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
protected virtual KeyParameter GenerateRecordMacKey(IStreamCipher cipher)
|
||||
{
|
||||
byte[] array = new byte[64];
|
||||
cipher.ProcessBytes(array, 0, array.Length, array, 0);
|
||||
KeyParameter result = new KeyParameter(array, 0, 32);
|
||||
Arrays.Fill(array, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected virtual byte[] CalculateRecordMac(KeyParameter macKey, byte[] additionalData, byte[] buf, int off, int len)
|
||||
{
|
||||
IMac mac = new Poly1305();
|
||||
mac.Init(macKey);
|
||||
UpdateRecordMacText(mac, additionalData, 0, additionalData.Length);
|
||||
UpdateRecordMacText(mac, buf, off, len);
|
||||
UpdateRecordMacLength(mac, additionalData.Length);
|
||||
UpdateRecordMacLength(mac, len);
|
||||
return MacUtilities.DoFinal(mac);
|
||||
}
|
||||
|
||||
protected virtual void UpdateRecordMacLength(IMac mac, int len)
|
||||
{
|
||||
byte[] array = Pack.UInt64_To_LE((ulong)len);
|
||||
mac.BlockUpdate(array, 0, array.Length);
|
||||
}
|
||||
|
||||
protected virtual void UpdateRecordMacText(IMac mac, byte[] buf, int off, int len)
|
||||
{
|
||||
mac.BlockUpdate(buf, off, len);
|
||||
int num = len % 16;
|
||||
if (num != 0)
|
||||
{
|
||||
mac.BlockUpdate(Zeroes, 0, 16 - num);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual byte[] GetAdditionalData(long seqNo, byte type, int len)
|
||||
{
|
||||
byte[] array = new byte[13];
|
||||
TlsUtilities.WriteUint64(seqNo, array, 0);
|
||||
TlsUtilities.WriteUint8(type, array, 8);
|
||||
TlsUtilities.WriteVersion(context.ServerVersion, array, 9);
|
||||
TlsUtilities.WriteUint16(len, array, 11);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ChangeCipherSpec
|
||||
{
|
||||
public const byte change_cipher_spec = 1;
|
||||
}
|
||||
@@ -0,0 +1,553 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class CipherSuite
|
||||
{
|
||||
public const int TLS_NULL_WITH_NULL_NULL = 0;
|
||||
|
||||
public const int TLS_RSA_WITH_NULL_MD5 = 1;
|
||||
|
||||
public const int TLS_RSA_WITH_NULL_SHA = 2;
|
||||
|
||||
public const int TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 3;
|
||||
|
||||
public const int TLS_RSA_WITH_RC4_128_MD5 = 4;
|
||||
|
||||
public const int TLS_RSA_WITH_RC4_128_SHA = 5;
|
||||
|
||||
public const int TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 6;
|
||||
|
||||
public const int TLS_RSA_WITH_IDEA_CBC_SHA = 7;
|
||||
|
||||
public const int TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 8;
|
||||
|
||||
public const int TLS_RSA_WITH_DES_CBC_SHA = 9;
|
||||
|
||||
public const int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 10;
|
||||
|
||||
public const int TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 11;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_DES_CBC_SHA = 12;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13;
|
||||
|
||||
public const int TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 14;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_DES_CBC_SHA = 15;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16;
|
||||
|
||||
public const int TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 17;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_DES_CBC_SHA = 18;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19;
|
||||
|
||||
public const int TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 20;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_DES_CBC_SHA = 21;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22;
|
||||
|
||||
public const int TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 23;
|
||||
|
||||
public const int TLS_DH_anon_WITH_RC4_128_MD5 = 24;
|
||||
|
||||
public const int TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 25;
|
||||
|
||||
public const int TLS_DH_anon_WITH_DES_CBC_SHA = 26;
|
||||
|
||||
public const int TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 27;
|
||||
|
||||
public const int TLS_RSA_WITH_AES_128_CBC_SHA = 47;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51;
|
||||
|
||||
public const int TLS_DH_anon_WITH_AES_128_CBC_SHA = 52;
|
||||
|
||||
public const int TLS_RSA_WITH_AES_256_CBC_SHA = 53;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57;
|
||||
|
||||
public const int TLS_DH_anon_WITH_AES_256_CBC_SHA = 58;
|
||||
|
||||
public const int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 65;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 66;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 67;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 68;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 69;
|
||||
|
||||
public const int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 70;
|
||||
|
||||
public const int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 132;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 133;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 134;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 135;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 136;
|
||||
|
||||
public const int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 137;
|
||||
|
||||
public const int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 186;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 187;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 188;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 189;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 190;
|
||||
|
||||
public const int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 = 191;
|
||||
|
||||
public const int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 192;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 193;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 194;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 195;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 196;
|
||||
|
||||
public const int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 = 197;
|
||||
|
||||
public const int TLS_RSA_WITH_SEED_CBC_SHA = 150;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_SEED_CBC_SHA = 151;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_SEED_CBC_SHA = 152;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_SEED_CBC_SHA = 153;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_SEED_CBC_SHA = 154;
|
||||
|
||||
public const int TLS_DH_anon_WITH_SEED_CBC_SHA = 155;
|
||||
|
||||
public const int TLS_PSK_WITH_RC4_128_SHA = 138;
|
||||
|
||||
public const int TLS_PSK_WITH_3DES_EDE_CBC_SHA = 139;
|
||||
|
||||
public const int TLS_PSK_WITH_AES_128_CBC_SHA = 140;
|
||||
|
||||
public const int TLS_PSK_WITH_AES_256_CBC_SHA = 141;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_RC4_128_SHA = 142;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 143;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 144;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 145;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_RC4_128_SHA = 146;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 147;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 148;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 149;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_NULL_SHA = 49153;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 49154;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 49155;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 49156;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 49157;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_NULL_SHA = 49158;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 49159;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 49160;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 49161;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 49162;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_NULL_SHA = 49163;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_RC4_128_SHA = 49164;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 49165;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 49166;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 49167;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_NULL_SHA = 49168;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_RC4_128_SHA = 49169;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 49170;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 49171;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 49172;
|
||||
|
||||
public const int TLS_ECDH_anon_WITH_NULL_SHA = 49173;
|
||||
|
||||
public const int TLS_ECDH_anon_WITH_RC4_128_SHA = 49174;
|
||||
|
||||
public const int TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 49175;
|
||||
|
||||
public const int TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 49176;
|
||||
|
||||
public const int TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 49177;
|
||||
|
||||
public const int TLS_PSK_WITH_NULL_SHA = 44;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_NULL_SHA = 45;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_NULL_SHA = 46;
|
||||
|
||||
public const int TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 49178;
|
||||
|
||||
public const int TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 49179;
|
||||
|
||||
public const int TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 49180;
|
||||
|
||||
public const int TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 49181;
|
||||
|
||||
public const int TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 49182;
|
||||
|
||||
public const int TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 49183;
|
||||
|
||||
public const int TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 49184;
|
||||
|
||||
public const int TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 49185;
|
||||
|
||||
public const int TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 49186;
|
||||
|
||||
public const int TLS_RSA_WITH_NULL_SHA256 = 59;
|
||||
|
||||
public const int TLS_RSA_WITH_AES_128_CBC_SHA256 = 60;
|
||||
|
||||
public const int TLS_RSA_WITH_AES_256_CBC_SHA256 = 61;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 62;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 63;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 64;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 103;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 104;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 105;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 106;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 107;
|
||||
|
||||
public const int TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 108;
|
||||
|
||||
public const int TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 109;
|
||||
|
||||
public const int TLS_RSA_WITH_AES_128_GCM_SHA256 = 156;
|
||||
|
||||
public const int TLS_RSA_WITH_AES_256_GCM_SHA384 = 157;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 158;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 159;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 160;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 161;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 162;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 163;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 164;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 165;
|
||||
|
||||
public const int TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 166;
|
||||
|
||||
public const int TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 167;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 49187;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 49188;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 49189;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 49190;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 49191;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 49192;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 49193;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 49194;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 49195;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 49196;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 49197;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 49198;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 49199;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 49200;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 49201;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 49202;
|
||||
|
||||
public const int TLS_PSK_WITH_AES_128_GCM_SHA256 = 168;
|
||||
|
||||
public const int TLS_PSK_WITH_AES_256_GCM_SHA384 = 169;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 170;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 171;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 172;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 173;
|
||||
|
||||
public const int TLS_PSK_WITH_AES_128_CBC_SHA256 = 174;
|
||||
|
||||
public const int TLS_PSK_WITH_AES_256_CBC_SHA384 = 175;
|
||||
|
||||
public const int TLS_PSK_WITH_NULL_SHA256 = 176;
|
||||
|
||||
public const int TLS_PSK_WITH_NULL_SHA384 = 177;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 178;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 179;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_NULL_SHA256 = 180;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_NULL_SHA384 = 181;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 182;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 183;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_NULL_SHA256 = 184;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_NULL_SHA384 = 185;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_RC4_128_SHA = 49203;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = 49204;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 49205;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 49206;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 49207;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = 49208;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_NULL_SHA = 49209;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_NULL_SHA256 = 49210;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_NULL_SHA384 = 49211;
|
||||
|
||||
public const int TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 255;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 49266;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 49267;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 49268;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 49269;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 49270;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 49271;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 49272;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 49273;
|
||||
|
||||
public const int TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 49274;
|
||||
|
||||
public const int TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 49275;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 49276;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 49277;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 49278;
|
||||
|
||||
public const int TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 49279;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 49280;
|
||||
|
||||
public const int TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 49281;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 49282;
|
||||
|
||||
public const int TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 49283;
|
||||
|
||||
public const int TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 = 49284;
|
||||
|
||||
public const int TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 = 49285;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 49286;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 49287;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 49288;
|
||||
|
||||
public const int TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 49289;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 49290;
|
||||
|
||||
public const int TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 49291;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 49292;
|
||||
|
||||
public const int TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 49293;
|
||||
|
||||
public const int TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 49294;
|
||||
|
||||
public const int TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 49295;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 49296;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 49297;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 49298;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 49299;
|
||||
|
||||
public const int TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 49300;
|
||||
|
||||
public const int TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 49301;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 49302;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 49303;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 49304;
|
||||
|
||||
public const int TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 49305;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 49306;
|
||||
|
||||
public const int TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 49307;
|
||||
|
||||
public const int TLS_RSA_WITH_AES_128_CCM = 49308;
|
||||
|
||||
public const int TLS_RSA_WITH_AES_256_CCM = 49309;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_AES_128_CCM = 49310;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_AES_256_CCM = 49311;
|
||||
|
||||
public const int TLS_RSA_WITH_AES_128_CCM_8 = 49312;
|
||||
|
||||
public const int TLS_RSA_WITH_AES_256_CCM_8 = 49313;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_AES_128_CCM_8 = 49314;
|
||||
|
||||
public const int TLS_DHE_RSA_WITH_AES_256_CCM_8 = 49315;
|
||||
|
||||
public const int TLS_PSK_WITH_AES_128_CCM = 49316;
|
||||
|
||||
public const int TLS_PSK_WITH_AES_256_CCM = 49317;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_AES_128_CCM = 49318;
|
||||
|
||||
public const int TLS_DHE_PSK_WITH_AES_256_CCM = 49319;
|
||||
|
||||
public const int TLS_PSK_WITH_AES_128_CCM_8 = 49320;
|
||||
|
||||
public const int TLS_PSK_WITH_AES_256_CCM_8 = 49321;
|
||||
|
||||
public const int TLS_PSK_DHE_WITH_AES_128_CCM_8 = 49322;
|
||||
|
||||
public const int TLS_PSK_DHE_WITH_AES_256_CCM_8 = 49323;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_AES_128_CCM = 49324;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_AES_256_CCM = 49325;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 49326;
|
||||
|
||||
public const int TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 49327;
|
||||
|
||||
public const int TLS_FALLBACK_SCSV = 22016;
|
||||
|
||||
public const int DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 52392;
|
||||
|
||||
public const int DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 52393;
|
||||
|
||||
public const int DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 52394;
|
||||
|
||||
public const int DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 = 52395;
|
||||
|
||||
public const int DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 52396;
|
||||
|
||||
public const int DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 52397;
|
||||
|
||||
public const int DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = 52398;
|
||||
|
||||
public const int DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB = 65280;
|
||||
|
||||
public const int DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB = 65281;
|
||||
|
||||
public const int DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB = 65282;
|
||||
|
||||
public const int DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB = 65283;
|
||||
|
||||
public const int DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB = 65284;
|
||||
|
||||
public const int DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB = 65285;
|
||||
|
||||
public const int DRAFT_TLS_PSK_WITH_AES_128_OCB = 65296;
|
||||
|
||||
public const int DRAFT_TLS_PSK_WITH_AES_256_OCB = 65297;
|
||||
|
||||
public const int DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB = 65298;
|
||||
|
||||
public const int DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB = 65299;
|
||||
|
||||
public const int DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB = 65300;
|
||||
|
||||
public const int DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB = 65301;
|
||||
|
||||
public static bool IsScsv(int cipherSuite)
|
||||
{
|
||||
if (cipherSuite == 255 || cipherSuite == 22016)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class CipherType
|
||||
{
|
||||
public const int stream = 0;
|
||||
|
||||
public const int block = 1;
|
||||
|
||||
public const int aead = 2;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ClientAuthenticationType
|
||||
{
|
||||
public const byte anonymous = 0;
|
||||
|
||||
public const byte certificate_based = 1;
|
||||
|
||||
public const byte psk = 2;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ClientCertificateType
|
||||
{
|
||||
public const byte rsa_sign = 1;
|
||||
|
||||
public const byte dss_sign = 2;
|
||||
|
||||
public const byte rsa_fixed_dh = 3;
|
||||
|
||||
public const byte dss_fixed_dh = 4;
|
||||
|
||||
public const byte rsa_ephemeral_dh_RESERVED = 5;
|
||||
|
||||
public const byte dss_ephemeral_dh_RESERVED = 6;
|
||||
|
||||
public const byte fortezza_dms_RESERVED = 20;
|
||||
|
||||
public const byte ecdsa_sign = 64;
|
||||
|
||||
public const byte rsa_fixed_ecdh = 65;
|
||||
|
||||
public const byte ecdsa_fixed_ecdh = 66;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal class CombinedHash : TlsHandshakeHash, IDigest
|
||||
{
|
||||
protected TlsContext mContext;
|
||||
|
||||
protected IDigest mMd5;
|
||||
|
||||
protected IDigest mSha1;
|
||||
|
||||
public virtual string AlgorithmName => mMd5.AlgorithmName + " and " + mSha1.AlgorithmName;
|
||||
|
||||
internal CombinedHash()
|
||||
{
|
||||
mMd5 = TlsUtilities.CreateHash(1);
|
||||
mSha1 = TlsUtilities.CreateHash(2);
|
||||
}
|
||||
|
||||
internal CombinedHash(CombinedHash t)
|
||||
{
|
||||
mContext = t.mContext;
|
||||
mMd5 = TlsUtilities.CloneHash(1, t.mMd5);
|
||||
mSha1 = TlsUtilities.CloneHash(2, t.mSha1);
|
||||
}
|
||||
|
||||
public virtual void Init(TlsContext context)
|
||||
{
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public virtual TlsHandshakeHash NotifyPrfDetermined()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual void TrackHashAlgorithm(byte hashAlgorithm)
|
||||
{
|
||||
throw new InvalidOperationException("CombinedHash only supports calculating the legacy PRF for handshake hash");
|
||||
}
|
||||
|
||||
public virtual void SealHashAlgorithms()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual TlsHandshakeHash StopTracking()
|
||||
{
|
||||
return new CombinedHash(this);
|
||||
}
|
||||
|
||||
public virtual IDigest ForkPrfHash()
|
||||
{
|
||||
return new CombinedHash(this);
|
||||
}
|
||||
|
||||
public virtual byte[] GetFinalHash(byte hashAlgorithm)
|
||||
{
|
||||
throw new InvalidOperationException("CombinedHash doesn't support multiple hashes");
|
||||
}
|
||||
|
||||
public virtual int GetByteLength()
|
||||
{
|
||||
return System.Math.Max(mMd5.GetByteLength(), mSha1.GetByteLength());
|
||||
}
|
||||
|
||||
public virtual int GetDigestSize()
|
||||
{
|
||||
return mMd5.GetDigestSize() + mSha1.GetDigestSize();
|
||||
}
|
||||
|
||||
public virtual void Update(byte input)
|
||||
{
|
||||
mMd5.Update(input);
|
||||
mSha1.Update(input);
|
||||
}
|
||||
|
||||
public virtual void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
mMd5.BlockUpdate(input, inOff, len);
|
||||
mSha1.BlockUpdate(input, inOff, len);
|
||||
}
|
||||
|
||||
public virtual int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
if (mContext != null && TlsUtilities.IsSsl(mContext))
|
||||
{
|
||||
Ssl3Complete(mMd5, Ssl3Mac.IPAD, Ssl3Mac.OPAD, 48);
|
||||
Ssl3Complete(mSha1, Ssl3Mac.IPAD, Ssl3Mac.OPAD, 40);
|
||||
}
|
||||
int num = mMd5.DoFinal(output, outOff);
|
||||
int num2 = mSha1.DoFinal(output, outOff + num);
|
||||
return num + num2;
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
mMd5.Reset();
|
||||
mSha1.Reset();
|
||||
}
|
||||
|
||||
protected virtual void Ssl3Complete(IDigest d, byte[] ipad, byte[] opad, int padLength)
|
||||
{
|
||||
byte[] masterSecret = mContext.SecurityParameters.masterSecret;
|
||||
d.BlockUpdate(masterSecret, 0, masterSecret.Length);
|
||||
d.BlockUpdate(ipad, 0, padLength);
|
||||
byte[] array = DigestUtilities.DoFinal(d);
|
||||
d.BlockUpdate(masterSecret, 0, masterSecret.Length);
|
||||
d.BlockUpdate(opad, 0, padLength);
|
||||
d.BlockUpdate(array, 0, array.Length);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class CompressionMethod
|
||||
{
|
||||
public const byte cls_null = 0;
|
||||
|
||||
public const byte DEFLATE = 1;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ConnectionEnd
|
||||
{
|
||||
public const int server = 0;
|
||||
|
||||
public const int client = 1;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ContentType
|
||||
{
|
||||
public const byte change_cipher_spec = 20;
|
||||
|
||||
public const byte alert = 21;
|
||||
|
||||
public const byte handshake = 22;
|
||||
|
||||
public const byte application_data = 23;
|
||||
|
||||
public const byte heartbeat = 24;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public interface DatagramTransport
|
||||
{
|
||||
int GetReceiveLimit();
|
||||
|
||||
int GetSendLimit();
|
||||
|
||||
int Receive(byte[] buf, int off, int len, int waitMillis);
|
||||
|
||||
void Send(byte[] buf, int off, int len);
|
||||
|
||||
void Close();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Agreement;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class DefaultTlsAgreementCredentials : AbstractTlsAgreementCredentials
|
||||
{
|
||||
protected readonly Certificate mCertificate;
|
||||
|
||||
protected readonly AsymmetricKeyParameter mPrivateKey;
|
||||
|
||||
protected readonly IBasicAgreement mBasicAgreement;
|
||||
|
||||
protected readonly bool mTruncateAgreement;
|
||||
|
||||
public override Certificate Certificate => mCertificate;
|
||||
|
||||
public DefaultTlsAgreementCredentials(Certificate certificate, AsymmetricKeyParameter privateKey)
|
||||
{
|
||||
if (certificate == null)
|
||||
{
|
||||
throw new ArgumentNullException("certificate");
|
||||
}
|
||||
if (certificate.IsEmpty)
|
||||
{
|
||||
throw new ArgumentException("cannot be empty", "certificate");
|
||||
}
|
||||
if (privateKey == null)
|
||||
{
|
||||
throw new ArgumentNullException("privateKey");
|
||||
}
|
||||
if (!privateKey.IsPrivate)
|
||||
{
|
||||
throw new ArgumentException("must be private", "privateKey");
|
||||
}
|
||||
if (privateKey is DHPrivateKeyParameters)
|
||||
{
|
||||
mBasicAgreement = new DHBasicAgreement();
|
||||
mTruncateAgreement = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(privateKey is ECPrivateKeyParameters))
|
||||
{
|
||||
throw new ArgumentException("type not supported: " + Platform.GetTypeName(privateKey), "privateKey");
|
||||
}
|
||||
mBasicAgreement = new ECDHBasicAgreement();
|
||||
mTruncateAgreement = false;
|
||||
}
|
||||
mCertificate = certificate;
|
||||
mPrivateKey = privateKey;
|
||||
}
|
||||
|
||||
public override byte[] GenerateAgreement(AsymmetricKeyParameter peerPublicKey)
|
||||
{
|
||||
mBasicAgreement.Init(mPrivateKey);
|
||||
BigInteger n = mBasicAgreement.CalculateAgreement(peerPublicKey);
|
||||
if (mTruncateAgreement)
|
||||
{
|
||||
return BigIntegers.AsUnsignedByteArray(n);
|
||||
}
|
||||
return BigIntegers.AsUnsignedByteArray(mBasicAgreement.GetFieldSize(), n);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Modes;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class DefaultTlsCipherFactory : AbstractTlsCipherFactory
|
||||
{
|
||||
public override TlsCipher CreateCipher(TlsContext context, int encryptionAlgorithm, int macAlgorithm)
|
||||
{
|
||||
return encryptionAlgorithm switch
|
||||
{
|
||||
7 => CreateDesEdeCipher(context, macAlgorithm),
|
||||
8 => CreateAESCipher(context, 16, macAlgorithm),
|
||||
15 => CreateCipher_Aes_Ccm(context, 16, 16),
|
||||
16 => CreateCipher_Aes_Ccm(context, 16, 8),
|
||||
10 => CreateCipher_Aes_Gcm(context, 16, 16),
|
||||
103 => CreateCipher_Aes_Ocb(context, 16, 12),
|
||||
9 => CreateAESCipher(context, 32, macAlgorithm),
|
||||
17 => CreateCipher_Aes_Ccm(context, 32, 16),
|
||||
18 => CreateCipher_Aes_Ccm(context, 32, 8),
|
||||
11 => CreateCipher_Aes_Gcm(context, 32, 16),
|
||||
104 => CreateCipher_Aes_Ocb(context, 32, 12),
|
||||
12 => CreateCamelliaCipher(context, 16, macAlgorithm),
|
||||
19 => CreateCipher_Camellia_Gcm(context, 16, 16),
|
||||
13 => CreateCamelliaCipher(context, 32, macAlgorithm),
|
||||
20 => CreateCipher_Camellia_Gcm(context, 32, 16),
|
||||
21 => CreateChaCha20Poly1305(context),
|
||||
0 => CreateNullCipher(context, macAlgorithm),
|
||||
2 => CreateRC4Cipher(context, 16, macAlgorithm),
|
||||
14 => CreateSeedCipher(context, macAlgorithm),
|
||||
_ => throw new TlsFatalAlert(80),
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual TlsBlockCipher CreateAESCipher(TlsContext context, int cipherKeySize, int macAlgorithm)
|
||||
{
|
||||
return new TlsBlockCipher(context, CreateAesBlockCipher(), CreateAesBlockCipher(), CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm), cipherKeySize);
|
||||
}
|
||||
|
||||
protected virtual TlsBlockCipher CreateCamelliaCipher(TlsContext context, int cipherKeySize, int macAlgorithm)
|
||||
{
|
||||
return new TlsBlockCipher(context, CreateCamelliaBlockCipher(), CreateCamelliaBlockCipher(), CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm), cipherKeySize);
|
||||
}
|
||||
|
||||
protected virtual TlsCipher CreateChaCha20Poly1305(TlsContext context)
|
||||
{
|
||||
return new Chacha20Poly1305(context);
|
||||
}
|
||||
|
||||
protected virtual TlsAeadCipher CreateCipher_Aes_Ccm(TlsContext context, int cipherKeySize, int macSize)
|
||||
{
|
||||
return new TlsAeadCipher(context, CreateAeadBlockCipher_Aes_Ccm(), CreateAeadBlockCipher_Aes_Ccm(), cipherKeySize, macSize);
|
||||
}
|
||||
|
||||
protected virtual TlsAeadCipher CreateCipher_Aes_Gcm(TlsContext context, int cipherKeySize, int macSize)
|
||||
{
|
||||
return new TlsAeadCipher(context, CreateAeadBlockCipher_Aes_Gcm(), CreateAeadBlockCipher_Aes_Gcm(), cipherKeySize, macSize);
|
||||
}
|
||||
|
||||
protected virtual TlsAeadCipher CreateCipher_Aes_Ocb(TlsContext context, int cipherKeySize, int macSize)
|
||||
{
|
||||
return new TlsAeadCipher(context, CreateAeadBlockCipher_Aes_Ocb(), CreateAeadBlockCipher_Aes_Ocb(), cipherKeySize, macSize, 2);
|
||||
}
|
||||
|
||||
protected virtual TlsAeadCipher CreateCipher_Camellia_Gcm(TlsContext context, int cipherKeySize, int macSize)
|
||||
{
|
||||
return new TlsAeadCipher(context, CreateAeadBlockCipher_Camellia_Gcm(), CreateAeadBlockCipher_Camellia_Gcm(), cipherKeySize, macSize);
|
||||
}
|
||||
|
||||
protected virtual TlsBlockCipher CreateDesEdeCipher(TlsContext context, int macAlgorithm)
|
||||
{
|
||||
return new TlsBlockCipher(context, CreateDesEdeBlockCipher(), CreateDesEdeBlockCipher(), CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm), 24);
|
||||
}
|
||||
|
||||
protected virtual TlsNullCipher CreateNullCipher(TlsContext context, int macAlgorithm)
|
||||
{
|
||||
return new TlsNullCipher(context, CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm));
|
||||
}
|
||||
|
||||
protected virtual TlsStreamCipher CreateRC4Cipher(TlsContext context, int cipherKeySize, int macAlgorithm)
|
||||
{
|
||||
return new TlsStreamCipher(context, CreateRC4StreamCipher(), CreateRC4StreamCipher(), CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm), cipherKeySize, usesNonce: false);
|
||||
}
|
||||
|
||||
protected virtual TlsBlockCipher CreateSeedCipher(TlsContext context, int macAlgorithm)
|
||||
{
|
||||
return new TlsBlockCipher(context, CreateSeedBlockCipher(), CreateSeedBlockCipher(), CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm), 16);
|
||||
}
|
||||
|
||||
protected virtual IBlockCipher CreateAesEngine()
|
||||
{
|
||||
return new AesEngine();
|
||||
}
|
||||
|
||||
protected virtual IBlockCipher CreateCamelliaEngine()
|
||||
{
|
||||
return new CamelliaEngine();
|
||||
}
|
||||
|
||||
protected virtual IBlockCipher CreateAesBlockCipher()
|
||||
{
|
||||
return new CbcBlockCipher(CreateAesEngine());
|
||||
}
|
||||
|
||||
protected virtual IAeadBlockCipher CreateAeadBlockCipher_Aes_Ccm()
|
||||
{
|
||||
return new CcmBlockCipher(CreateAesEngine());
|
||||
}
|
||||
|
||||
protected virtual IAeadBlockCipher CreateAeadBlockCipher_Aes_Gcm()
|
||||
{
|
||||
return new GcmBlockCipher(CreateAesEngine());
|
||||
}
|
||||
|
||||
protected virtual IAeadBlockCipher CreateAeadBlockCipher_Aes_Ocb()
|
||||
{
|
||||
return new OcbBlockCipher(CreateAesEngine(), CreateAesEngine());
|
||||
}
|
||||
|
||||
protected virtual IAeadBlockCipher CreateAeadBlockCipher_Camellia_Gcm()
|
||||
{
|
||||
return new GcmBlockCipher(CreateCamelliaEngine());
|
||||
}
|
||||
|
||||
protected virtual IBlockCipher CreateCamelliaBlockCipher()
|
||||
{
|
||||
return new CbcBlockCipher(CreateCamelliaEngine());
|
||||
}
|
||||
|
||||
protected virtual IBlockCipher CreateDesEdeBlockCipher()
|
||||
{
|
||||
return new CbcBlockCipher(new DesEdeEngine());
|
||||
}
|
||||
|
||||
protected virtual IStreamCipher CreateRC4StreamCipher()
|
||||
{
|
||||
return new RC4Engine();
|
||||
}
|
||||
|
||||
protected virtual IBlockCipher CreateSeedBlockCipher()
|
||||
{
|
||||
return new CbcBlockCipher(new SeedEngine());
|
||||
}
|
||||
|
||||
protected virtual IDigest CreateHMacDigest(int macAlgorithm)
|
||||
{
|
||||
return macAlgorithm switch
|
||||
{
|
||||
0 => null,
|
||||
1 => TlsUtilities.CreateHash(1),
|
||||
2 => TlsUtilities.CreateHash(2),
|
||||
3 => TlsUtilities.CreateHash(4),
|
||||
4 => TlsUtilities.CreateHash(5),
|
||||
5 => TlsUtilities.CreateHash(6),
|
||||
_ => throw new TlsFatalAlert(80),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class DefaultTlsClient : AbstractTlsClient
|
||||
{
|
||||
protected TlsDHVerifier mDHVerifier;
|
||||
|
||||
public DefaultTlsClient()
|
||||
: this(new DefaultTlsCipherFactory())
|
||||
{
|
||||
}
|
||||
|
||||
public DefaultTlsClient(TlsCipherFactory cipherFactory)
|
||||
: this(cipherFactory, new DefaultTlsDHVerifier())
|
||||
{
|
||||
}
|
||||
|
||||
public DefaultTlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier)
|
||||
: base(cipherFactory)
|
||||
{
|
||||
mDHVerifier = dhVerifier;
|
||||
}
|
||||
|
||||
public override int[] GetCipherSuites()
|
||||
{
|
||||
return new int[9] { 49195, 49187, 49161, 49199, 49191, 49171, 156, 60, 47 };
|
||||
}
|
||||
|
||||
public override TlsKeyExchange GetKeyExchange()
|
||||
{
|
||||
int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
|
||||
switch (keyExchangeAlgorithm)
|
||||
{
|
||||
case 7:
|
||||
case 9:
|
||||
case 11:
|
||||
return CreateDHKeyExchange(keyExchangeAlgorithm);
|
||||
case 3:
|
||||
case 5:
|
||||
return CreateDheKeyExchange(keyExchangeAlgorithm);
|
||||
case 16:
|
||||
case 18:
|
||||
case 20:
|
||||
return CreateECDHKeyExchange(keyExchangeAlgorithm);
|
||||
case 17:
|
||||
case 19:
|
||||
return CreateECDheKeyExchange(keyExchangeAlgorithm);
|
||||
case 1:
|
||||
return CreateRsaKeyExchange();
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mDHVerifier, null);
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mDHVerifier, null);
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsECDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mNamedCurves, mClientECPointFormats, mServerECPointFormats);
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateECDheKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsECDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mNamedCurves, mClientECPointFormats, mServerECPointFormats);
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateRsaKeyExchange()
|
||||
{
|
||||
return new TlsRsaKeyExchange(mSupportedSignatureAlgorithms);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
using System.Collections;
|
||||
using Org.BouncyCastle.Crypto.Agreement;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class DefaultTlsDHVerifier : TlsDHVerifier
|
||||
{
|
||||
public static readonly int DefaultMinimumPrimeBits;
|
||||
|
||||
protected static readonly IList DefaultGroups;
|
||||
|
||||
protected readonly IList mGroups;
|
||||
|
||||
protected readonly int mMinimumPrimeBits;
|
||||
|
||||
public virtual int MinimumPrimeBits => mMinimumPrimeBits;
|
||||
|
||||
private static void AddDefaultGroup(DHParameters dhParameters)
|
||||
{
|
||||
DefaultGroups.Add(dhParameters);
|
||||
}
|
||||
|
||||
static DefaultTlsDHVerifier()
|
||||
{
|
||||
DefaultMinimumPrimeBits = 2048;
|
||||
DefaultGroups = Platform.CreateArrayList();
|
||||
AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe2048);
|
||||
AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe3072);
|
||||
AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe4096);
|
||||
AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe6144);
|
||||
AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe8192);
|
||||
AddDefaultGroup(DHStandardGroups.rfc3526_1536);
|
||||
AddDefaultGroup(DHStandardGroups.rfc3526_2048);
|
||||
AddDefaultGroup(DHStandardGroups.rfc3526_3072);
|
||||
AddDefaultGroup(DHStandardGroups.rfc3526_4096);
|
||||
AddDefaultGroup(DHStandardGroups.rfc3526_6144);
|
||||
AddDefaultGroup(DHStandardGroups.rfc3526_8192);
|
||||
}
|
||||
|
||||
public DefaultTlsDHVerifier()
|
||||
: this(DefaultMinimumPrimeBits)
|
||||
{
|
||||
}
|
||||
|
||||
public DefaultTlsDHVerifier(int minimumPrimeBits)
|
||||
: this(DefaultGroups, minimumPrimeBits)
|
||||
{
|
||||
}
|
||||
|
||||
public DefaultTlsDHVerifier(IList groups, int minimumPrimeBits)
|
||||
{
|
||||
mGroups = groups;
|
||||
mMinimumPrimeBits = minimumPrimeBits;
|
||||
}
|
||||
|
||||
public virtual bool Accept(DHParameters dhParameters)
|
||||
{
|
||||
if (CheckMinimumPrimeBits(dhParameters))
|
||||
{
|
||||
return CheckGroup(dhParameters);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual bool AreGroupsEqual(DHParameters a, DHParameters b)
|
||||
{
|
||||
if (a != b)
|
||||
{
|
||||
if (AreParametersEqual(a.P, b.P))
|
||||
{
|
||||
return AreParametersEqual(a.G, b.G);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual bool AreParametersEqual(BigInteger a, BigInteger b)
|
||||
{
|
||||
if (a != b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual bool CheckGroup(DHParameters dhParameters)
|
||||
{
|
||||
foreach (DHParameters mGroup in mGroups)
|
||||
{
|
||||
if (AreGroupsEqual(dhParameters, mGroup))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual bool CheckMinimumPrimeBits(DHParameters dhParameters)
|
||||
{
|
||||
return dhParameters.P.BitLength >= MinimumPrimeBits;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class DefaultTlsEncryptionCredentials : AbstractTlsEncryptionCredentials
|
||||
{
|
||||
protected readonly TlsContext mContext;
|
||||
|
||||
protected readonly Certificate mCertificate;
|
||||
|
||||
protected readonly AsymmetricKeyParameter mPrivateKey;
|
||||
|
||||
public override Certificate Certificate => mCertificate;
|
||||
|
||||
public DefaultTlsEncryptionCredentials(TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey)
|
||||
{
|
||||
if (certificate == null)
|
||||
{
|
||||
throw new ArgumentNullException("certificate");
|
||||
}
|
||||
if (certificate.IsEmpty)
|
||||
{
|
||||
throw new ArgumentException("cannot be empty", "certificate");
|
||||
}
|
||||
if (privateKey == null)
|
||||
{
|
||||
throw new ArgumentNullException("'privateKey' cannot be null");
|
||||
}
|
||||
if (!privateKey.IsPrivate)
|
||||
{
|
||||
throw new ArgumentException("must be private", "privateKey");
|
||||
}
|
||||
if (!(privateKey is RsaKeyParameters))
|
||||
{
|
||||
throw new ArgumentException("type not supported: " + Platform.GetTypeName(privateKey), "privateKey");
|
||||
}
|
||||
mContext = context;
|
||||
mCertificate = certificate;
|
||||
mPrivateKey = privateKey;
|
||||
}
|
||||
|
||||
public override byte[] DecryptPreMasterSecret(byte[] encryptedPreMasterSecret)
|
||||
{
|
||||
return TlsRsaUtilities.SafeDecryptPreMasterSecret(mContext, (RsaKeyParameters)mPrivateKey, encryptedPreMasterSecret);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using Org.BouncyCastle.Crypto.Agreement;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class DefaultTlsServer : AbstractTlsServer
|
||||
{
|
||||
public DefaultTlsServer()
|
||||
{
|
||||
}
|
||||
|
||||
public DefaultTlsServer(TlsCipherFactory cipherFactory)
|
||||
: base(cipherFactory)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual TlsSignerCredentials GetDsaSignerCredentials()
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
protected virtual TlsSignerCredentials GetECDsaSignerCredentials()
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
protected virtual TlsEncryptionCredentials GetRsaEncryptionCredentials()
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
protected virtual TlsSignerCredentials GetRsaSignerCredentials()
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
protected virtual DHParameters GetDHParameters()
|
||||
{
|
||||
return DHStandardGroups.rfc7919_ffdhe2048;
|
||||
}
|
||||
|
||||
protected override int[] GetCipherSuites()
|
||||
{
|
||||
return new int[18]
|
||||
{
|
||||
49200, 49199, 49192, 49191, 49172, 49171, 159, 158, 107, 103,
|
||||
57, 51, 157, 156, 61, 60, 53, 47
|
||||
};
|
||||
}
|
||||
|
||||
public override TlsCredentials GetCredentials()
|
||||
{
|
||||
switch (TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite))
|
||||
{
|
||||
case 3:
|
||||
return GetDsaSignerCredentials();
|
||||
case 11:
|
||||
case 20:
|
||||
return null;
|
||||
case 17:
|
||||
return GetECDsaSignerCredentials();
|
||||
case 5:
|
||||
case 19:
|
||||
return GetRsaSignerCredentials();
|
||||
case 1:
|
||||
return GetRsaEncryptionCredentials();
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
}
|
||||
|
||||
public override TlsKeyExchange GetKeyExchange()
|
||||
{
|
||||
int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
|
||||
switch (keyExchangeAlgorithm)
|
||||
{
|
||||
case 7:
|
||||
case 9:
|
||||
case 11:
|
||||
return CreateDHKeyExchange(keyExchangeAlgorithm);
|
||||
case 3:
|
||||
case 5:
|
||||
return CreateDheKeyExchange(keyExchangeAlgorithm);
|
||||
case 16:
|
||||
case 18:
|
||||
case 20:
|
||||
return CreateECDHKeyExchange(keyExchangeAlgorithm);
|
||||
case 17:
|
||||
case 19:
|
||||
return CreateECDheKeyExchange(keyExchangeAlgorithm);
|
||||
case 1:
|
||||
return CreateRsaKeyExchange();
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, GetDHParameters());
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, GetDHParameters());
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsECDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mNamedCurves, mClientECPointFormats, mServerECPointFormats);
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateECDheKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsECDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mNamedCurves, mClientECPointFormats, mServerECPointFormats);
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateRsaKeyExchange()
|
||||
{
|
||||
return new TlsRsaKeyExchange(mSupportedSignatureAlgorithms);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class DefaultTlsSignerCredentials : AbstractTlsSignerCredentials
|
||||
{
|
||||
protected readonly TlsContext mContext;
|
||||
|
||||
protected readonly Certificate mCertificate;
|
||||
|
||||
protected readonly AsymmetricKeyParameter mPrivateKey;
|
||||
|
||||
protected readonly SignatureAndHashAlgorithm mSignatureAndHashAlgorithm;
|
||||
|
||||
protected readonly TlsSigner mSigner;
|
||||
|
||||
public override Certificate Certificate => mCertificate;
|
||||
|
||||
public override SignatureAndHashAlgorithm SignatureAndHashAlgorithm => mSignatureAndHashAlgorithm;
|
||||
|
||||
public DefaultTlsSignerCredentials(TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey)
|
||||
: this(context, certificate, privateKey, null)
|
||||
{
|
||||
}
|
||||
|
||||
public DefaultTlsSignerCredentials(TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey, SignatureAndHashAlgorithm signatureAndHashAlgorithm)
|
||||
{
|
||||
if (certificate == null)
|
||||
{
|
||||
throw new ArgumentNullException("certificate");
|
||||
}
|
||||
if (certificate.IsEmpty)
|
||||
{
|
||||
throw new ArgumentException("cannot be empty", "clientCertificate");
|
||||
}
|
||||
if (privateKey == null)
|
||||
{
|
||||
throw new ArgumentNullException("privateKey");
|
||||
}
|
||||
if (!privateKey.IsPrivate)
|
||||
{
|
||||
throw new ArgumentException("must be private", "privateKey");
|
||||
}
|
||||
if (TlsUtilities.IsTlsV12(context) && signatureAndHashAlgorithm == null)
|
||||
{
|
||||
throw new ArgumentException("cannot be null for (D)TLS 1.2+", "signatureAndHashAlgorithm");
|
||||
}
|
||||
if (privateKey is RsaKeyParameters)
|
||||
{
|
||||
mSigner = new TlsRsaSigner();
|
||||
}
|
||||
else if (privateKey is DsaPrivateKeyParameters)
|
||||
{
|
||||
mSigner = new TlsDssSigner();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(privateKey is ECPrivateKeyParameters))
|
||||
{
|
||||
throw new ArgumentException("type not supported: " + Platform.GetTypeName(privateKey), "privateKey");
|
||||
}
|
||||
mSigner = new TlsECDsaSigner();
|
||||
}
|
||||
mSigner.Init(context);
|
||||
mContext = context;
|
||||
mCertificate = certificate;
|
||||
mPrivateKey = privateKey;
|
||||
mSignatureAndHashAlgorithm = signatureAndHashAlgorithm;
|
||||
}
|
||||
|
||||
public override byte[] GenerateCertificateSignature(byte[] hash)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (TlsUtilities.IsTlsV12(mContext))
|
||||
{
|
||||
return mSigner.GenerateRawSignature(mSignatureAndHashAlgorithm, mPrivateKey, hash);
|
||||
}
|
||||
return mSigner.GenerateRawSignature(mPrivateKey, hash);
|
||||
}
|
||||
catch (CryptoException alertCause)
|
||||
{
|
||||
throw new TlsFatalAlert(80, alertCause);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System.Collections;
|
||||
using Org.BouncyCastle.Crypto.Agreement.Srp;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class DefaultTlsSrpGroupVerifier : TlsSrpGroupVerifier
|
||||
{
|
||||
protected static readonly IList DefaultGroups;
|
||||
|
||||
protected readonly IList mGroups;
|
||||
|
||||
static DefaultTlsSrpGroupVerifier()
|
||||
{
|
||||
DefaultGroups = Platform.CreateArrayList();
|
||||
DefaultGroups.Add(Srp6StandardGroups.rfc5054_1024);
|
||||
DefaultGroups.Add(Srp6StandardGroups.rfc5054_1536);
|
||||
DefaultGroups.Add(Srp6StandardGroups.rfc5054_2048);
|
||||
DefaultGroups.Add(Srp6StandardGroups.rfc5054_3072);
|
||||
DefaultGroups.Add(Srp6StandardGroups.rfc5054_4096);
|
||||
DefaultGroups.Add(Srp6StandardGroups.rfc5054_6144);
|
||||
DefaultGroups.Add(Srp6StandardGroups.rfc5054_8192);
|
||||
}
|
||||
|
||||
public DefaultTlsSrpGroupVerifier()
|
||||
: this(DefaultGroups)
|
||||
{
|
||||
}
|
||||
|
||||
public DefaultTlsSrpGroupVerifier(IList groups)
|
||||
{
|
||||
mGroups = groups;
|
||||
}
|
||||
|
||||
public virtual bool Accept(Srp6GroupParameters group)
|
||||
{
|
||||
foreach (Srp6GroupParameters mGroup in mGroups)
|
||||
{
|
||||
if (AreGroupsEqual(group, mGroup))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual bool AreGroupsEqual(Srp6GroupParameters a, Srp6GroupParameters b)
|
||||
{
|
||||
if (a != b)
|
||||
{
|
||||
if (AreParametersEqual(a.N, b.N))
|
||||
{
|
||||
return AreParametersEqual(a.G, b.G);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual bool AreParametersEqual(BigInteger a, BigInteger b)
|
||||
{
|
||||
if (a != b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal class DeferredHash : TlsHandshakeHash, IDigest
|
||||
{
|
||||
protected const int BUFFERING_HASH_LIMIT = 4;
|
||||
|
||||
protected TlsContext mContext;
|
||||
|
||||
private DigestInputBuffer mBuf;
|
||||
|
||||
private IDictionary mHashes;
|
||||
|
||||
private int mPrfHashAlgorithm;
|
||||
|
||||
public virtual string AlgorithmName
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new InvalidOperationException("Use Fork() to get a definite IDigest");
|
||||
}
|
||||
}
|
||||
|
||||
internal DeferredHash()
|
||||
{
|
||||
mBuf = new DigestInputBuffer();
|
||||
mHashes = Platform.CreateHashtable();
|
||||
mPrfHashAlgorithm = -1;
|
||||
}
|
||||
|
||||
private DeferredHash(byte prfHashAlgorithm, IDigest prfHash)
|
||||
{
|
||||
mBuf = null;
|
||||
mHashes = Platform.CreateHashtable();
|
||||
mPrfHashAlgorithm = prfHashAlgorithm;
|
||||
mHashes[prfHashAlgorithm] = prfHash;
|
||||
}
|
||||
|
||||
public virtual void Init(TlsContext context)
|
||||
{
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public virtual TlsHandshakeHash NotifyPrfDetermined()
|
||||
{
|
||||
int prfAlgorithm = mContext.SecurityParameters.PrfAlgorithm;
|
||||
if (prfAlgorithm == 0)
|
||||
{
|
||||
CombinedHash combinedHash = new CombinedHash();
|
||||
combinedHash.Init(mContext);
|
||||
mBuf.UpdateDigest(combinedHash);
|
||||
return combinedHash.NotifyPrfDetermined();
|
||||
}
|
||||
mPrfHashAlgorithm = TlsUtilities.GetHashAlgorithmForPrfAlgorithm(prfAlgorithm);
|
||||
CheckTrackingHash((byte)mPrfHashAlgorithm);
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual void TrackHashAlgorithm(byte hashAlgorithm)
|
||||
{
|
||||
if (mBuf == null)
|
||||
{
|
||||
throw new InvalidOperationException("Too late to track more hash algorithms");
|
||||
}
|
||||
CheckTrackingHash(hashAlgorithm);
|
||||
}
|
||||
|
||||
public virtual void SealHashAlgorithms()
|
||||
{
|
||||
CheckStopBuffering();
|
||||
}
|
||||
|
||||
public virtual TlsHandshakeHash StopTracking()
|
||||
{
|
||||
byte b = (byte)mPrfHashAlgorithm;
|
||||
IDigest digest = TlsUtilities.CloneHash(b, (IDigest)mHashes[b]);
|
||||
if (mBuf != null)
|
||||
{
|
||||
mBuf.UpdateDigest(digest);
|
||||
}
|
||||
DeferredHash deferredHash = new DeferredHash(b, digest);
|
||||
deferredHash.Init(mContext);
|
||||
return deferredHash;
|
||||
}
|
||||
|
||||
public virtual IDigest ForkPrfHash()
|
||||
{
|
||||
CheckStopBuffering();
|
||||
byte b = (byte)mPrfHashAlgorithm;
|
||||
if (mBuf != null)
|
||||
{
|
||||
IDigest digest = TlsUtilities.CreateHash(b);
|
||||
mBuf.UpdateDigest(digest);
|
||||
return digest;
|
||||
}
|
||||
return TlsUtilities.CloneHash(b, (IDigest)mHashes[b]);
|
||||
}
|
||||
|
||||
public virtual byte[] GetFinalHash(byte hashAlgorithm)
|
||||
{
|
||||
IDigest digest = (IDigest)mHashes[hashAlgorithm];
|
||||
if (digest == null)
|
||||
{
|
||||
throw new InvalidOperationException("HashAlgorithm." + HashAlgorithm.GetText(hashAlgorithm) + " is not being tracked");
|
||||
}
|
||||
digest = TlsUtilities.CloneHash(hashAlgorithm, digest);
|
||||
if (mBuf != null)
|
||||
{
|
||||
mBuf.UpdateDigest(digest);
|
||||
}
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
public virtual int GetByteLength()
|
||||
{
|
||||
throw new InvalidOperationException("Use Fork() to get a definite IDigest");
|
||||
}
|
||||
|
||||
public virtual int GetDigestSize()
|
||||
{
|
||||
throw new InvalidOperationException("Use Fork() to get a definite IDigest");
|
||||
}
|
||||
|
||||
public virtual void Update(byte input)
|
||||
{
|
||||
if (mBuf != null)
|
||||
{
|
||||
mBuf.WriteByte(input);
|
||||
return;
|
||||
}
|
||||
foreach (IDigest value in mHashes.Values)
|
||||
{
|
||||
value.Update(input);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
if (mBuf != null)
|
||||
{
|
||||
mBuf.Write(input, inOff, len);
|
||||
return;
|
||||
}
|
||||
foreach (IDigest value in mHashes.Values)
|
||||
{
|
||||
value.BlockUpdate(input, inOff, len);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
throw new InvalidOperationException("Use Fork() to get a definite IDigest");
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
if (mBuf != null)
|
||||
{
|
||||
mBuf.SetLength(0L);
|
||||
return;
|
||||
}
|
||||
foreach (IDigest value in mHashes.Values)
|
||||
{
|
||||
value.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CheckStopBuffering()
|
||||
{
|
||||
if (mBuf == null || mHashes.Count > 4)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (IDigest value in mHashes.Values)
|
||||
{
|
||||
mBuf.UpdateDigest(value);
|
||||
}
|
||||
mBuf = null;
|
||||
}
|
||||
|
||||
protected virtual void CheckTrackingHash(byte hashAlgorithm)
|
||||
{
|
||||
if (!mHashes.Contains(hashAlgorithm))
|
||||
{
|
||||
IDigest value = TlsUtilities.CreateHash(hashAlgorithm);
|
||||
mHashes[hashAlgorithm] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal class DigestInputBuffer : MemoryStream
|
||||
{
|
||||
private class DigStream : BaseOutputStream
|
||||
{
|
||||
private readonly IDigest d;
|
||||
|
||||
internal DigStream(IDigest d)
|
||||
{
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public override void WriteByte(byte b)
|
||||
{
|
||||
d.Update(b);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buf, int off, int len)
|
||||
{
|
||||
d.BlockUpdate(buf, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateDigest(IDigest d)
|
||||
{
|
||||
Streams.WriteBufTo(this, new DigStream(d));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class DigitallySigned
|
||||
{
|
||||
protected readonly SignatureAndHashAlgorithm mAlgorithm;
|
||||
|
||||
protected readonly byte[] mSignature;
|
||||
|
||||
public virtual SignatureAndHashAlgorithm Algorithm => mAlgorithm;
|
||||
|
||||
public virtual byte[] Signature => mSignature;
|
||||
|
||||
public DigitallySigned(SignatureAndHashAlgorithm algorithm, byte[] signature)
|
||||
{
|
||||
if (signature == null)
|
||||
{
|
||||
throw new ArgumentNullException("signature");
|
||||
}
|
||||
mAlgorithm = algorithm;
|
||||
mSignature = signature;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
if (mAlgorithm != null)
|
||||
{
|
||||
mAlgorithm.Encode(output);
|
||||
}
|
||||
TlsUtilities.WriteOpaque16(mSignature, output);
|
||||
}
|
||||
|
||||
public static DigitallySigned Parse(TlsContext context, Stream input)
|
||||
{
|
||||
SignatureAndHashAlgorithm algorithm = null;
|
||||
if (TlsUtilities.IsTlsV12(context))
|
||||
{
|
||||
algorithm = SignatureAndHashAlgorithm.Parse(input);
|
||||
}
|
||||
byte[] signature = TlsUtilities.ReadOpaque16(input);
|
||||
return new DigitallySigned(algorithm, signature);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,567 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class DtlsClientProtocol : DtlsProtocol
|
||||
{
|
||||
protected internal class ClientHandshakeState
|
||||
{
|
||||
internal TlsClient client = null;
|
||||
|
||||
internal TlsClientContextImpl clientContext = null;
|
||||
|
||||
internal TlsSession tlsSession = null;
|
||||
|
||||
internal SessionParameters sessionParameters = null;
|
||||
|
||||
internal SessionParameters.Builder sessionParametersBuilder = null;
|
||||
|
||||
internal int[] offeredCipherSuites = null;
|
||||
|
||||
internal IDictionary clientExtensions = null;
|
||||
|
||||
internal IDictionary serverExtensions = null;
|
||||
|
||||
internal byte[] selectedSessionID = null;
|
||||
|
||||
internal bool resumedSession = false;
|
||||
|
||||
internal bool secure_renegotiation = false;
|
||||
|
||||
internal bool allowCertificateStatus = false;
|
||||
|
||||
internal bool expectSessionTicket = false;
|
||||
|
||||
internal TlsKeyExchange keyExchange = null;
|
||||
|
||||
internal TlsAuthentication authentication = null;
|
||||
|
||||
internal CertificateStatus certificateStatus = null;
|
||||
|
||||
internal CertificateRequest certificateRequest = null;
|
||||
|
||||
internal TlsCredentials clientCredentials = null;
|
||||
}
|
||||
|
||||
public DtlsClientProtocol(SecureRandom secureRandom)
|
||||
: base(secureRandom)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual DtlsTransport Connect(TlsClient client, DatagramTransport transport)
|
||||
{
|
||||
if (client == null)
|
||||
{
|
||||
throw new ArgumentNullException("client");
|
||||
}
|
||||
if (transport == null)
|
||||
{
|
||||
throw new ArgumentNullException("transport");
|
||||
}
|
||||
SecurityParameters securityParameters = new SecurityParameters();
|
||||
securityParameters.entity = 1;
|
||||
ClientHandshakeState clientHandshakeState = new ClientHandshakeState();
|
||||
clientHandshakeState.client = client;
|
||||
clientHandshakeState.clientContext = new TlsClientContextImpl(mSecureRandom, securityParameters);
|
||||
securityParameters.clientRandom = TlsProtocol.CreateRandomBlock(client.ShouldUseGmtUnixTime(), clientHandshakeState.clientContext.NonceRandomGenerator);
|
||||
client.Init(clientHandshakeState.clientContext);
|
||||
DtlsRecordLayer recordLayer = new DtlsRecordLayer(transport, clientHandshakeState.clientContext, client, 22);
|
||||
TlsSession sessionToResume = clientHandshakeState.client.GetSessionToResume();
|
||||
if (sessionToResume != null && sessionToResume.IsResumable)
|
||||
{
|
||||
SessionParameters sessionParameters = sessionToResume.ExportSessionParameters();
|
||||
if (sessionParameters != null && sessionParameters.IsExtendedMasterSecret)
|
||||
{
|
||||
clientHandshakeState.tlsSession = sessionToResume;
|
||||
clientHandshakeState.sessionParameters = sessionParameters;
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
return ClientHandshake(clientHandshakeState, recordLayer);
|
||||
}
|
||||
catch (TlsFatalAlert tlsFatalAlert)
|
||||
{
|
||||
AbortClientHandshake(clientHandshakeState, recordLayer, tlsFatalAlert.AlertDescription);
|
||||
throw tlsFatalAlert;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
AbortClientHandshake(clientHandshakeState, recordLayer, 80);
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception alertCause)
|
||||
{
|
||||
AbortClientHandshake(clientHandshakeState, recordLayer, 80);
|
||||
throw new TlsFatalAlert(80, alertCause);
|
||||
}
|
||||
finally
|
||||
{
|
||||
securityParameters.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void AbortClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer, byte alertDescription)
|
||||
{
|
||||
recordLayer.Fail(alertDescription);
|
||||
InvalidateSession(state);
|
||||
}
|
||||
|
||||
internal virtual DtlsTransport ClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer)
|
||||
{
|
||||
SecurityParameters securityParameters = state.clientContext.SecurityParameters;
|
||||
DtlsReliableHandshake dtlsReliableHandshake = new DtlsReliableHandshake(state.clientContext, recordLayer);
|
||||
byte[] array = GenerateClientHello(state, state.client);
|
||||
recordLayer.SetWriteVersion(ProtocolVersion.DTLSv10);
|
||||
dtlsReliableHandshake.SendMessage(1, array);
|
||||
DtlsReliableHandshake.Message message = dtlsReliableHandshake.ReceiveMessage();
|
||||
while (message.Type == 3)
|
||||
{
|
||||
ProtocolVersion readVersion = recordLayer.ReadVersion;
|
||||
ProtocolVersion clientVersion = state.clientContext.ClientVersion;
|
||||
if (!readVersion.IsEqualOrEarlierVersionOf(clientVersion))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
recordLayer.ReadVersion = null;
|
||||
byte[] cookie = ProcessHelloVerifyRequest(state, message.Body);
|
||||
byte[] body = PatchClientHelloWithCookie(array, cookie);
|
||||
dtlsReliableHandshake.ResetHandshakeMessagesDigest();
|
||||
dtlsReliableHandshake.SendMessage(1, body);
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
}
|
||||
if (message.Type == 2)
|
||||
{
|
||||
ProtocolVersion readVersion2 = recordLayer.ReadVersion;
|
||||
ReportServerVersion(state, readVersion2);
|
||||
recordLayer.SetWriteVersion(readVersion2);
|
||||
ProcessServerHello(state, message.Body);
|
||||
dtlsReliableHandshake.NotifyHelloComplete();
|
||||
DtlsProtocol.ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.maxFragmentLength);
|
||||
if (state.resumedSession)
|
||||
{
|
||||
securityParameters.masterSecret = Arrays.Clone(state.sessionParameters.MasterSecret);
|
||||
recordLayer.InitPendingEpoch(state.client.GetCipher());
|
||||
byte[] expected_verify_data = TlsUtilities.CalculateVerifyData(state.clientContext, "server finished", TlsProtocol.GetCurrentPrfHash(state.clientContext, dtlsReliableHandshake.HandshakeHash, null));
|
||||
ProcessFinished(dtlsReliableHandshake.ReceiveMessageBody(20), expected_verify_data);
|
||||
byte[] body2 = TlsUtilities.CalculateVerifyData(state.clientContext, "client finished", TlsProtocol.GetCurrentPrfHash(state.clientContext, dtlsReliableHandshake.HandshakeHash, null));
|
||||
dtlsReliableHandshake.SendMessage(20, body2);
|
||||
dtlsReliableHandshake.Finish();
|
||||
state.clientContext.SetResumableSession(state.tlsSession);
|
||||
state.client.NotifyHandshakeComplete();
|
||||
return new DtlsTransport(recordLayer);
|
||||
}
|
||||
InvalidateSession(state);
|
||||
if (state.selectedSessionID.Length > 0)
|
||||
{
|
||||
state.tlsSession = new TlsSessionImpl(state.selectedSessionID, null);
|
||||
}
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
if (message.Type == 23)
|
||||
{
|
||||
ProcessServerSupplementalData(state, message.Body);
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.client.ProcessServerSupplementalData(null);
|
||||
}
|
||||
state.keyExchange = state.client.GetKeyExchange();
|
||||
state.keyExchange.Init(state.clientContext);
|
||||
Certificate certificate = null;
|
||||
if (message.Type == 11)
|
||||
{
|
||||
certificate = ProcessServerCertificate(state, message.Body);
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.keyExchange.SkipServerCredentials();
|
||||
}
|
||||
if (certificate == null || certificate.IsEmpty)
|
||||
{
|
||||
state.allowCertificateStatus = false;
|
||||
}
|
||||
if (message.Type == 22)
|
||||
{
|
||||
ProcessCertificateStatus(state, message.Body);
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
}
|
||||
if (message.Type == 12)
|
||||
{
|
||||
ProcessServerKeyExchange(state, message.Body);
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.keyExchange.SkipServerKeyExchange();
|
||||
}
|
||||
if (message.Type == 13)
|
||||
{
|
||||
ProcessCertificateRequest(state, message.Body);
|
||||
TlsUtilities.TrackHashAlgorithms(dtlsReliableHandshake.HandshakeHash, state.certificateRequest.SupportedSignatureAlgorithms);
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
}
|
||||
if (message.Type == 14)
|
||||
{
|
||||
if (message.Body.Length != 0)
|
||||
{
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
dtlsReliableHandshake.HandshakeHash.SealHashAlgorithms();
|
||||
IList clientSupplementalData = state.client.GetClientSupplementalData();
|
||||
if (clientSupplementalData != null)
|
||||
{
|
||||
byte[] body3 = DtlsProtocol.GenerateSupplementalData(clientSupplementalData);
|
||||
dtlsReliableHandshake.SendMessage(23, body3);
|
||||
}
|
||||
if (state.certificateRequest != null)
|
||||
{
|
||||
state.clientCredentials = state.authentication.GetClientCredentials(state.certificateRequest);
|
||||
Certificate certificate2 = null;
|
||||
if (state.clientCredentials != null)
|
||||
{
|
||||
certificate2 = state.clientCredentials.Certificate;
|
||||
}
|
||||
if (certificate2 == null)
|
||||
{
|
||||
certificate2 = Certificate.EmptyChain;
|
||||
}
|
||||
byte[] body4 = DtlsProtocol.GenerateCertificate(certificate2);
|
||||
dtlsReliableHandshake.SendMessage(11, body4);
|
||||
}
|
||||
if (state.clientCredentials != null)
|
||||
{
|
||||
state.keyExchange.ProcessClientCredentials(state.clientCredentials);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.keyExchange.SkipClientCredentials();
|
||||
}
|
||||
byte[] body5 = GenerateClientKeyExchange(state);
|
||||
dtlsReliableHandshake.SendMessage(16, body5);
|
||||
TlsHandshakeHash tlsHandshakeHash = dtlsReliableHandshake.PrepareToFinish();
|
||||
securityParameters.sessionHash = TlsProtocol.GetCurrentPrfHash(state.clientContext, tlsHandshakeHash, null);
|
||||
TlsProtocol.EstablishMasterSecret(state.clientContext, state.keyExchange);
|
||||
recordLayer.InitPendingEpoch(state.client.GetCipher());
|
||||
if (state.clientCredentials != null && state.clientCredentials is TlsSignerCredentials)
|
||||
{
|
||||
TlsSignerCredentials tlsSignerCredentials = (TlsSignerCredentials)state.clientCredentials;
|
||||
SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm(state.clientContext, tlsSignerCredentials);
|
||||
byte[] hash = ((signatureAndHashAlgorithm != null) ? tlsHandshakeHash.GetFinalHash(signatureAndHashAlgorithm.Hash) : securityParameters.SessionHash);
|
||||
byte[] signature = tlsSignerCredentials.GenerateCertificateSignature(hash);
|
||||
DigitallySigned certificateVerify = new DigitallySigned(signatureAndHashAlgorithm, signature);
|
||||
byte[] body6 = GenerateCertificateVerify(state, certificateVerify);
|
||||
dtlsReliableHandshake.SendMessage(15, body6);
|
||||
}
|
||||
byte[] body7 = TlsUtilities.CalculateVerifyData(state.clientContext, "client finished", TlsProtocol.GetCurrentPrfHash(state.clientContext, dtlsReliableHandshake.HandshakeHash, null));
|
||||
dtlsReliableHandshake.SendMessage(20, body7);
|
||||
if (state.expectSessionTicket)
|
||||
{
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
if (message.Type != 4)
|
||||
{
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
ProcessNewSessionTicket(state, message.Body);
|
||||
}
|
||||
byte[] expected_verify_data2 = TlsUtilities.CalculateVerifyData(state.clientContext, "server finished", TlsProtocol.GetCurrentPrfHash(state.clientContext, dtlsReliableHandshake.HandshakeHash, null));
|
||||
ProcessFinished(dtlsReliableHandshake.ReceiveMessageBody(20), expected_verify_data2);
|
||||
dtlsReliableHandshake.Finish();
|
||||
if (state.tlsSession != null)
|
||||
{
|
||||
state.sessionParameters = new SessionParameters.Builder().SetCipherSuite(securityParameters.CipherSuite).SetCompressionAlgorithm(securityParameters.CompressionAlgorithm).SetExtendedMasterSecret(securityParameters.IsExtendedMasterSecret)
|
||||
.SetMasterSecret(securityParameters.MasterSecret)
|
||||
.SetPeerCertificate(certificate)
|
||||
.SetPskIdentity(securityParameters.PskIdentity)
|
||||
.SetSrpIdentity(securityParameters.SrpIdentity)
|
||||
.SetServerExtensions(state.serverExtensions)
|
||||
.Build();
|
||||
state.tlsSession = TlsUtilities.ImportSession(state.tlsSession.SessionID, state.sessionParameters);
|
||||
state.clientContext.SetResumableSession(state.tlsSession);
|
||||
}
|
||||
state.client.NotifyHandshakeComplete();
|
||||
return new DtlsTransport(recordLayer);
|
||||
}
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
|
||||
protected virtual byte[] GenerateCertificateVerify(ClientHandshakeState state, DigitallySigned certificateVerify)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
certificateVerify.Encode(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
protected virtual byte[] GenerateClientHello(ClientHandshakeState state, TlsClient client)
|
||||
{
|
||||
ProtocolVersion clientVersion = client.ClientVersion;
|
||||
if (!clientVersion.IsDtls)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
TlsClientContextImpl clientContext = state.clientContext;
|
||||
clientContext.SetClientVersion(clientVersion);
|
||||
SecurityParameters securityParameters = clientContext.SecurityParameters;
|
||||
byte[] array = TlsUtilities.EmptyBytes;
|
||||
if (state.tlsSession != null)
|
||||
{
|
||||
array = state.tlsSession.SessionID;
|
||||
if (array == null || array.Length > 32)
|
||||
{
|
||||
array = TlsUtilities.EmptyBytes;
|
||||
}
|
||||
}
|
||||
bool isFallback = client.IsFallback;
|
||||
state.offeredCipherSuites = client.GetCipherSuites();
|
||||
if (array.Length > 0 && state.sessionParameters != null && (!state.sessionParameters.IsExtendedMasterSecret || !Arrays.Contains(state.offeredCipherSuites, state.sessionParameters.CipherSuite) || state.sessionParameters.CompressionAlgorithm != 0))
|
||||
{
|
||||
array = TlsUtilities.EmptyBytes;
|
||||
}
|
||||
state.clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(client.GetClientExtensions());
|
||||
TlsExtensionsUtilities.AddExtendedMasterSecretExtension(state.clientExtensions);
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
TlsUtilities.WriteVersion(clientVersion, memoryStream);
|
||||
memoryStream.Write(securityParameters.ClientRandom, 0, securityParameters.ClientRandom.Length);
|
||||
TlsUtilities.WriteOpaque8(array, memoryStream);
|
||||
TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, memoryStream);
|
||||
byte[] extensionData = TlsUtilities.GetExtensionData(state.clientExtensions, 65281);
|
||||
bool flag = null == extensionData;
|
||||
bool flag2 = !Arrays.Contains(state.offeredCipherSuites, 255);
|
||||
if (flag && flag2)
|
||||
{
|
||||
state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, 255);
|
||||
}
|
||||
if (isFallback && !Arrays.Contains(state.offeredCipherSuites, 22016))
|
||||
{
|
||||
state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, 22016);
|
||||
}
|
||||
TlsUtilities.WriteUint16ArrayWithUint16Length(state.offeredCipherSuites, memoryStream);
|
||||
byte[] uints = new byte[1];
|
||||
TlsUtilities.WriteUint8ArrayWithUint8Length(uints, memoryStream);
|
||||
TlsProtocol.WriteExtensions(memoryStream, state.clientExtensions);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
protected virtual byte[] GenerateClientKeyExchange(ClientHandshakeState state)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
state.keyExchange.GenerateClientKeyExchange(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
protected virtual void InvalidateSession(ClientHandshakeState state)
|
||||
{
|
||||
if (state.sessionParameters != null)
|
||||
{
|
||||
state.sessionParameters.Clear();
|
||||
state.sessionParameters = null;
|
||||
}
|
||||
if (state.tlsSession != null)
|
||||
{
|
||||
state.tlsSession.Invalidate();
|
||||
state.tlsSession = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ProcessCertificateRequest(ClientHandshakeState state, byte[] body)
|
||||
{
|
||||
if (state.authentication == null)
|
||||
{
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
MemoryStream memoryStream = new MemoryStream(body, writable: false);
|
||||
state.certificateRequest = CertificateRequest.Parse(state.clientContext, memoryStream);
|
||||
TlsProtocol.AssertEmpty(memoryStream);
|
||||
state.keyExchange.ValidateCertificateRequest(state.certificateRequest);
|
||||
}
|
||||
|
||||
protected virtual void ProcessCertificateStatus(ClientHandshakeState state, byte[] body)
|
||||
{
|
||||
if (!state.allowCertificateStatus)
|
||||
{
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
MemoryStream memoryStream = new MemoryStream(body, writable: false);
|
||||
state.certificateStatus = CertificateStatus.Parse(memoryStream);
|
||||
TlsProtocol.AssertEmpty(memoryStream);
|
||||
}
|
||||
|
||||
protected virtual byte[] ProcessHelloVerifyRequest(ClientHandshakeState state, byte[] body)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream(body, writable: false);
|
||||
ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(memoryStream);
|
||||
byte[] array = TlsUtilities.ReadOpaque8(memoryStream);
|
||||
TlsProtocol.AssertEmpty(memoryStream);
|
||||
if (!protocolVersion.IsEqualOrEarlierVersionOf(state.clientContext.ClientVersion))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
if (!ProtocolVersion.DTLSv12.IsEqualOrEarlierVersionOf(protocolVersion) && array.Length > 32)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
protected virtual void ProcessNewSessionTicket(ClientHandshakeState state, byte[] body)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream(body, writable: false);
|
||||
NewSessionTicket newSessionTicket = NewSessionTicket.Parse(memoryStream);
|
||||
TlsProtocol.AssertEmpty(memoryStream);
|
||||
state.client.NotifyNewSessionTicket(newSessionTicket);
|
||||
}
|
||||
|
||||
protected virtual Certificate ProcessServerCertificate(ClientHandshakeState state, byte[] body)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream(body, writable: false);
|
||||
Certificate certificate = Certificate.Parse(memoryStream);
|
||||
TlsProtocol.AssertEmpty(memoryStream);
|
||||
state.keyExchange.ProcessServerCertificate(certificate);
|
||||
state.authentication = state.client.GetAuthentication();
|
||||
state.authentication.NotifyServerCertificate(certificate);
|
||||
return certificate;
|
||||
}
|
||||
|
||||
protected virtual void ProcessServerHello(ClientHandshakeState state, byte[] body)
|
||||
{
|
||||
SecurityParameters securityParameters = state.clientContext.SecurityParameters;
|
||||
MemoryStream input = new MemoryStream(body, writable: false);
|
||||
ProtocolVersion server_version = TlsUtilities.ReadVersion(input);
|
||||
ReportServerVersion(state, server_version);
|
||||
securityParameters.serverRandom = TlsUtilities.ReadFully(32, input);
|
||||
state.selectedSessionID = TlsUtilities.ReadOpaque8(input);
|
||||
if (state.selectedSessionID.Length > 32)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
state.client.NotifySessionID(state.selectedSessionID);
|
||||
state.resumedSession = state.selectedSessionID.Length > 0 && state.tlsSession != null && Arrays.AreEqual(state.selectedSessionID, state.tlsSession.SessionID);
|
||||
int num = TlsUtilities.ReadUint16(input);
|
||||
if (!Arrays.Contains(state.offeredCipherSuites, num) || num == 0 || CipherSuite.IsScsv(num) || !TlsUtilities.IsValidCipherSuiteForVersion(num, state.clientContext.ServerVersion))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
DtlsProtocol.ValidateSelectedCipherSuite(num, 47);
|
||||
state.client.NotifySelectedCipherSuite(num);
|
||||
byte b = TlsUtilities.ReadUint8(input);
|
||||
if (b != 0)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
state.client.NotifySelectedCompressionMethod(b);
|
||||
state.serverExtensions = TlsProtocol.ReadExtensions(input);
|
||||
securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.serverExtensions);
|
||||
if (!securityParameters.IsExtendedMasterSecret && (state.resumedSession || state.client.RequiresExtendedMasterSecret()))
|
||||
{
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
if (state.serverExtensions != null)
|
||||
{
|
||||
foreach (object key in state.serverExtensions.Keys)
|
||||
{
|
||||
int num2 = (int)key;
|
||||
if (num2 != 65281)
|
||||
{
|
||||
if (TlsUtilities.GetExtensionData(state.clientExtensions, num2) == null)
|
||||
{
|
||||
throw new TlsFatalAlert(110);
|
||||
}
|
||||
_ = state.resumedSession;
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] extensionData = TlsUtilities.GetExtensionData(state.serverExtensions, 65281);
|
||||
if (extensionData != null)
|
||||
{
|
||||
state.secure_renegotiation = true;
|
||||
if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
|
||||
{
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
}
|
||||
state.client.NotifySecureRenegotiation(state.secure_renegotiation);
|
||||
IDictionary dictionary = state.clientExtensions;
|
||||
IDictionary dictionary2 = state.serverExtensions;
|
||||
if (state.resumedSession)
|
||||
{
|
||||
if (num != state.sessionParameters.CipherSuite || b != state.sessionParameters.CompressionAlgorithm)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
dictionary = null;
|
||||
dictionary2 = state.sessionParameters.ReadServerExtensions();
|
||||
}
|
||||
securityParameters.cipherSuite = num;
|
||||
securityParameters.compressionAlgorithm = b;
|
||||
if (dictionary2 != null && dictionary2.Count > 0)
|
||||
{
|
||||
bool flag = TlsExtensionsUtilities.HasEncryptThenMacExtension(dictionary2);
|
||||
if (flag && !TlsUtilities.IsBlockCipherSuite(securityParameters.CipherSuite))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
securityParameters.encryptThenMac = flag;
|
||||
securityParameters.maxFragmentLength = DtlsProtocol.EvaluateMaxFragmentLengthExtension(state.resumedSession, dictionary, dictionary2, 47);
|
||||
securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(dictionary2);
|
||||
state.allowCertificateStatus = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 5, 47);
|
||||
state.expectSessionTicket = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 35, 47);
|
||||
}
|
||||
if (dictionary != null)
|
||||
{
|
||||
state.client.ProcessServerExtensions(dictionary2);
|
||||
}
|
||||
securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.clientContext, securityParameters.CipherSuite);
|
||||
securityParameters.verifyDataLength = 12;
|
||||
}
|
||||
|
||||
protected virtual void ProcessServerKeyExchange(ClientHandshakeState state, byte[] body)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream(body, writable: false);
|
||||
state.keyExchange.ProcessServerKeyExchange(memoryStream);
|
||||
TlsProtocol.AssertEmpty(memoryStream);
|
||||
}
|
||||
|
||||
protected virtual void ProcessServerSupplementalData(ClientHandshakeState state, byte[] body)
|
||||
{
|
||||
MemoryStream input = new MemoryStream(body, writable: false);
|
||||
IList serverSupplementalData = TlsProtocol.ReadSupplementalDataMessage(input);
|
||||
state.client.ProcessServerSupplementalData(serverSupplementalData);
|
||||
}
|
||||
|
||||
protected virtual void ReportServerVersion(ClientHandshakeState state, ProtocolVersion server_version)
|
||||
{
|
||||
TlsClientContextImpl clientContext = state.clientContext;
|
||||
ProtocolVersion serverVersion = clientContext.ServerVersion;
|
||||
if (serverVersion == null)
|
||||
{
|
||||
clientContext.SetServerVersion(server_version);
|
||||
state.client.NotifyServerVersion(server_version);
|
||||
}
|
||||
else if (!serverVersion.Equals(server_version))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
}
|
||||
|
||||
protected static byte[] PatchClientHelloWithCookie(byte[] clientHelloBody, byte[] cookie)
|
||||
{
|
||||
int num = 34;
|
||||
int num2 = TlsUtilities.ReadUint8(clientHelloBody, num);
|
||||
int num3 = num + 1 + num2;
|
||||
int num4 = num3 + 1;
|
||||
byte[] array = new byte[clientHelloBody.Length + cookie.Length];
|
||||
Array.Copy(clientHelloBody, 0, array, 0, num3);
|
||||
TlsUtilities.CheckUint8(cookie.Length);
|
||||
TlsUtilities.WriteUint8((byte)cookie.Length, array, num3);
|
||||
Array.Copy(cookie, 0, array, num4, cookie.Length);
|
||||
Array.Copy(clientHelloBody, num4, array, num4 + cookie.Length, clientHelloBody.Length - num4);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal class DtlsEpoch
|
||||
{
|
||||
private readonly DtlsReplayWindow mReplayWindow = new DtlsReplayWindow();
|
||||
|
||||
private readonly int mEpoch;
|
||||
|
||||
private readonly TlsCipher mCipher;
|
||||
|
||||
private long mSequenceNumber = 0L;
|
||||
|
||||
internal TlsCipher Cipher => mCipher;
|
||||
|
||||
internal int Epoch => mEpoch;
|
||||
|
||||
internal DtlsReplayWindow ReplayWindow => mReplayWindow;
|
||||
|
||||
internal long SequenceNumber => mSequenceNumber;
|
||||
|
||||
internal DtlsEpoch(int epoch, TlsCipher cipher)
|
||||
{
|
||||
if (epoch < 0)
|
||||
{
|
||||
throw new ArgumentException("must be >= 0", "epoch");
|
||||
}
|
||||
if (cipher == null)
|
||||
{
|
||||
throw new ArgumentNullException("cipher");
|
||||
}
|
||||
mEpoch = epoch;
|
||||
mCipher = cipher;
|
||||
}
|
||||
|
||||
internal long AllocateSequenceNumber()
|
||||
{
|
||||
return mSequenceNumber++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal interface DtlsHandshakeRetransmit
|
||||
{
|
||||
void ReceivedHandshakeRecord(int epoch, byte[] buf, int off, int len);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class DtlsProtocol
|
||||
{
|
||||
protected readonly SecureRandom mSecureRandom;
|
||||
|
||||
protected DtlsProtocol(SecureRandom secureRandom)
|
||||
{
|
||||
if (secureRandom == null)
|
||||
{
|
||||
throw new ArgumentNullException("secureRandom");
|
||||
}
|
||||
mSecureRandom = secureRandom;
|
||||
}
|
||||
|
||||
protected virtual void ProcessFinished(byte[] body, byte[] expected_verify_data)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream(body, writable: false);
|
||||
byte[] b = TlsUtilities.ReadFully(expected_verify_data.Length, memoryStream);
|
||||
TlsProtocol.AssertEmpty(memoryStream);
|
||||
if (!Arrays.ConstantTimeAreEqual(expected_verify_data, b))
|
||||
{
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ApplyMaxFragmentLengthExtension(DtlsRecordLayer recordLayer, short maxFragmentLength)
|
||||
{
|
||||
if (maxFragmentLength >= 0)
|
||||
{
|
||||
if (!MaxFragmentLength.IsValid((byte)maxFragmentLength))
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
int plaintextLimit = 1 << 8 + maxFragmentLength;
|
||||
recordLayer.SetPlaintextLimit(plaintextLimit);
|
||||
}
|
||||
}
|
||||
|
||||
protected static short EvaluateMaxFragmentLengthExtension(bool resumedSession, IDictionary clientExtensions, IDictionary serverExtensions, byte alertDescription)
|
||||
{
|
||||
short maxFragmentLengthExtension = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(serverExtensions);
|
||||
if (maxFragmentLengthExtension >= 0 && (!MaxFragmentLength.IsValid((byte)maxFragmentLengthExtension) || (!resumedSession && maxFragmentLengthExtension != TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions))))
|
||||
{
|
||||
throw new TlsFatalAlert(alertDescription);
|
||||
}
|
||||
return maxFragmentLengthExtension;
|
||||
}
|
||||
|
||||
protected static byte[] GenerateCertificate(Certificate certificate)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
certificate.Encode(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
protected static byte[] GenerateSupplementalData(IList supplementalData)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
TlsProtocol.WriteSupplementalData(memoryStream, supplementalData);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
protected static void ValidateSelectedCipherSuite(int selectedCipherSuite, byte alertDescription)
|
||||
{
|
||||
switch (TlsUtilities.GetEncryptionAlgorithm(selectedCipherSuite))
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
throw new TlsFatalAlert(alertDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal class DtlsReassembler
|
||||
{
|
||||
private class Range
|
||||
{
|
||||
private int mStart;
|
||||
|
||||
private int mEnd;
|
||||
|
||||
public int Start
|
||||
{
|
||||
get
|
||||
{
|
||||
return mStart;
|
||||
}
|
||||
set
|
||||
{
|
||||
mStart = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int End
|
||||
{
|
||||
get
|
||||
{
|
||||
return mEnd;
|
||||
}
|
||||
set
|
||||
{
|
||||
mEnd = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal Range(int start, int end)
|
||||
{
|
||||
mStart = start;
|
||||
mEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly byte mMsgType;
|
||||
|
||||
private readonly byte[] mBody;
|
||||
|
||||
private readonly IList mMissing = Platform.CreateArrayList();
|
||||
|
||||
internal byte MsgType => mMsgType;
|
||||
|
||||
internal DtlsReassembler(byte msg_type, int length)
|
||||
{
|
||||
mMsgType = msg_type;
|
||||
mBody = new byte[length];
|
||||
mMissing.Add(new Range(0, length));
|
||||
}
|
||||
|
||||
internal byte[] GetBodyIfComplete()
|
||||
{
|
||||
if (mMissing.Count != 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return mBody;
|
||||
}
|
||||
|
||||
internal void ContributeFragment(byte msg_type, int length, byte[] buf, int off, int fragment_offset, int fragment_length)
|
||||
{
|
||||
int num = fragment_offset + fragment_length;
|
||||
if (mMsgType != msg_type || mBody.Length != length || num > length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (fragment_length == 0)
|
||||
{
|
||||
if (fragment_offset == 0 && mMissing.Count > 0)
|
||||
{
|
||||
Range range = (Range)mMissing[0];
|
||||
if (range.End == 0)
|
||||
{
|
||||
mMissing.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < mMissing.Count; i++)
|
||||
{
|
||||
Range range2 = (Range)mMissing[i];
|
||||
if (range2.Start >= num)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (range2.End <= fragment_offset)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int num2 = System.Math.Max(range2.Start, fragment_offset);
|
||||
int num3 = System.Math.Min(range2.End, num);
|
||||
int length2 = num3 - num2;
|
||||
Array.Copy(buf, off + num2 - fragment_offset, mBody, num2, length2);
|
||||
if (num2 == range2.Start)
|
||||
{
|
||||
if (num3 == range2.End)
|
||||
{
|
||||
mMissing.RemoveAt(i--);
|
||||
}
|
||||
else
|
||||
{
|
||||
range2.Start = num3;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (num3 != range2.End)
|
||||
{
|
||||
mMissing.Insert(++i, new Range(num3, range2.End));
|
||||
}
|
||||
range2.End = num2;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Reset()
|
||||
{
|
||||
mMissing.Clear();
|
||||
mMissing.Add(new Range(0, mBody.Length));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Utilities.Date;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal class DtlsRecordLayer : DatagramTransport
|
||||
{
|
||||
private const int RECORD_HEADER_LENGTH = 13;
|
||||
|
||||
private const int MAX_FRAGMENT_LENGTH = 16384;
|
||||
|
||||
private const long TCP_MSL = 120000L;
|
||||
|
||||
private const long RETRANSMIT_TIMEOUT = 240000L;
|
||||
|
||||
private readonly DatagramTransport mTransport;
|
||||
|
||||
private readonly TlsContext mContext;
|
||||
|
||||
private readonly TlsPeer mPeer;
|
||||
|
||||
private readonly ByteQueue mRecordQueue = new ByteQueue();
|
||||
|
||||
private volatile bool mClosed = false;
|
||||
|
||||
private volatile bool mFailed = false;
|
||||
|
||||
private volatile ProtocolVersion mReadVersion = null;
|
||||
|
||||
private volatile ProtocolVersion mWriteVersion = null;
|
||||
|
||||
private volatile bool mInHandshake;
|
||||
|
||||
private volatile int mPlaintextLimit;
|
||||
|
||||
private DtlsEpoch mCurrentEpoch;
|
||||
|
||||
private DtlsEpoch mPendingEpoch;
|
||||
|
||||
private DtlsEpoch mReadEpoch;
|
||||
|
||||
private DtlsEpoch mWriteEpoch;
|
||||
|
||||
private DtlsHandshakeRetransmit mRetransmit = null;
|
||||
|
||||
private DtlsEpoch mRetransmitEpoch = null;
|
||||
|
||||
private long mRetransmitExpiry = 0L;
|
||||
|
||||
internal virtual int ReadEpoch => mReadEpoch.Epoch;
|
||||
|
||||
internal virtual ProtocolVersion ReadVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return mReadVersion;
|
||||
}
|
||||
set
|
||||
{
|
||||
mReadVersion = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal DtlsRecordLayer(DatagramTransport transport, TlsContext context, TlsPeer peer, byte contentType)
|
||||
{
|
||||
mTransport = transport;
|
||||
mContext = context;
|
||||
mPeer = peer;
|
||||
mInHandshake = true;
|
||||
mCurrentEpoch = new DtlsEpoch(0, new TlsNullCipher(context));
|
||||
mPendingEpoch = null;
|
||||
mReadEpoch = mCurrentEpoch;
|
||||
mWriteEpoch = mCurrentEpoch;
|
||||
SetPlaintextLimit(16384);
|
||||
}
|
||||
|
||||
internal virtual void SetPlaintextLimit(int plaintextLimit)
|
||||
{
|
||||
mPlaintextLimit = plaintextLimit;
|
||||
}
|
||||
|
||||
internal virtual void SetWriteVersion(ProtocolVersion writeVersion)
|
||||
{
|
||||
mWriteVersion = writeVersion;
|
||||
}
|
||||
|
||||
internal virtual void InitPendingEpoch(TlsCipher pendingCipher)
|
||||
{
|
||||
if (mPendingEpoch != null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
mPendingEpoch = new DtlsEpoch(mWriteEpoch.Epoch + 1, pendingCipher);
|
||||
}
|
||||
|
||||
internal virtual void HandshakeSuccessful(DtlsHandshakeRetransmit retransmit)
|
||||
{
|
||||
if (mReadEpoch == mCurrentEpoch || mWriteEpoch == mCurrentEpoch)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
if (retransmit != null)
|
||||
{
|
||||
mRetransmit = retransmit;
|
||||
mRetransmitEpoch = mCurrentEpoch;
|
||||
mRetransmitExpiry = DateTimeUtilities.CurrentUnixMs() + 240000;
|
||||
}
|
||||
mInHandshake = false;
|
||||
mCurrentEpoch = mPendingEpoch;
|
||||
mPendingEpoch = null;
|
||||
}
|
||||
|
||||
internal virtual void ResetWriteEpoch()
|
||||
{
|
||||
if (mRetransmitEpoch != null)
|
||||
{
|
||||
mWriteEpoch = mRetransmitEpoch;
|
||||
}
|
||||
else
|
||||
{
|
||||
mWriteEpoch = mCurrentEpoch;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int GetReceiveLimit()
|
||||
{
|
||||
return System.Math.Min(mPlaintextLimit, mReadEpoch.Cipher.GetPlaintextLimit(mTransport.GetReceiveLimit() - 13));
|
||||
}
|
||||
|
||||
public virtual int GetSendLimit()
|
||||
{
|
||||
return System.Math.Min(mPlaintextLimit, mWriteEpoch.Cipher.GetPlaintextLimit(mTransport.GetSendLimit() - 13));
|
||||
}
|
||||
|
||||
public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
|
||||
{
|
||||
byte[] array = null;
|
||||
while (true)
|
||||
{
|
||||
int num = System.Math.Min(len, GetReceiveLimit()) + 13;
|
||||
if (array == null || array.Length < num)
|
||||
{
|
||||
array = new byte[num];
|
||||
}
|
||||
try
|
||||
{
|
||||
if (mRetransmit != null && DateTimeUtilities.CurrentUnixMs() > mRetransmitExpiry)
|
||||
{
|
||||
mRetransmit = null;
|
||||
mRetransmitEpoch = null;
|
||||
}
|
||||
int num2 = ReceiveRecord(array, 0, num, waitMillis);
|
||||
if (num2 < 0)
|
||||
{
|
||||
return num2;
|
||||
}
|
||||
if (num2 < 13)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int num3 = TlsUtilities.ReadUint16(array, 11);
|
||||
if (num2 != num3 + 13)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
byte b = TlsUtilities.ReadUint8(array, 0);
|
||||
switch (b)
|
||||
{
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
{
|
||||
int num4 = TlsUtilities.ReadUint16(array, 3);
|
||||
DtlsEpoch dtlsEpoch = null;
|
||||
if (num4 == mReadEpoch.Epoch)
|
||||
{
|
||||
dtlsEpoch = mReadEpoch;
|
||||
}
|
||||
else if (b == 22 && mRetransmitEpoch != null && num4 == mRetransmitEpoch.Epoch)
|
||||
{
|
||||
dtlsEpoch = mRetransmitEpoch;
|
||||
}
|
||||
if (dtlsEpoch == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
long num5 = TlsUtilities.ReadUint48(array, 5);
|
||||
if (dtlsEpoch.ReplayWindow.ShouldDiscard(num5))
|
||||
{
|
||||
break;
|
||||
}
|
||||
ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(array, 1);
|
||||
if (!protocolVersion.IsDtls || (mReadVersion != null && !mReadVersion.Equals(protocolVersion)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
byte[] array2 = dtlsEpoch.Cipher.DecodeCiphertext(GetMacSequenceNumber(dtlsEpoch.Epoch, num5), b, array, 13, num2 - 13);
|
||||
dtlsEpoch.ReplayWindow.ReportAuthenticated(num5);
|
||||
if (array2.Length > mPlaintextLimit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (mReadVersion == null)
|
||||
{
|
||||
mReadVersion = protocolVersion;
|
||||
}
|
||||
switch (b)
|
||||
{
|
||||
case 21:
|
||||
if (array2.Length == 2)
|
||||
{
|
||||
byte b2 = array2[0];
|
||||
byte b3 = array2[1];
|
||||
mPeer.NotifyAlertReceived(b2, b3);
|
||||
if (b2 == 2)
|
||||
{
|
||||
Failed();
|
||||
throw new TlsFatalAlert(b3);
|
||||
}
|
||||
if (b3 == 0)
|
||||
{
|
||||
CloseTransport();
|
||||
}
|
||||
}
|
||||
goto end_IL_0088;
|
||||
case 23:
|
||||
if (!mInHandshake)
|
||||
{
|
||||
break;
|
||||
}
|
||||
goto end_IL_0088;
|
||||
case 20:
|
||||
{
|
||||
for (int i = 0; i < array2.Length; i++)
|
||||
{
|
||||
byte b4 = TlsUtilities.ReadUint8(array2, i);
|
||||
if (b4 == 1 && mPendingEpoch != null)
|
||||
{
|
||||
mReadEpoch = mPendingEpoch;
|
||||
}
|
||||
}
|
||||
goto end_IL_0088;
|
||||
}
|
||||
case 22:
|
||||
if (mInHandshake)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (mRetransmit != null)
|
||||
{
|
||||
mRetransmit.ReceivedHandshakeRecord(num4, array2, 0, array2.Length);
|
||||
}
|
||||
goto end_IL_0088;
|
||||
case 24:
|
||||
goto end_IL_0088;
|
||||
}
|
||||
if (!mInHandshake && mRetransmit != null)
|
||||
{
|
||||
mRetransmit = null;
|
||||
mRetransmitEpoch = null;
|
||||
}
|
||||
Array.Copy(array2, 0, buf, off, array2.Length);
|
||||
return array2.Length;
|
||||
}
|
||||
end_IL_0088:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Send(byte[] buf, int off, int len)
|
||||
{
|
||||
byte contentType = 23;
|
||||
if (mInHandshake || mWriteEpoch == mRetransmitEpoch)
|
||||
{
|
||||
contentType = 22;
|
||||
byte b = TlsUtilities.ReadUint8(buf, off);
|
||||
if (b == 20)
|
||||
{
|
||||
DtlsEpoch dtlsEpoch = null;
|
||||
if (mInHandshake)
|
||||
{
|
||||
dtlsEpoch = mPendingEpoch;
|
||||
}
|
||||
else if (mWriteEpoch == mRetransmitEpoch)
|
||||
{
|
||||
dtlsEpoch = mCurrentEpoch;
|
||||
}
|
||||
if (dtlsEpoch == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
byte[] array = new byte[1] { 1 };
|
||||
SendRecord(20, array, 0, array.Length);
|
||||
mWriteEpoch = dtlsEpoch;
|
||||
}
|
||||
}
|
||||
SendRecord(contentType, buf, off, len);
|
||||
}
|
||||
|
||||
public virtual void Close()
|
||||
{
|
||||
if (!mClosed)
|
||||
{
|
||||
if (mInHandshake)
|
||||
{
|
||||
Warn(90, "User canceled handshake");
|
||||
}
|
||||
CloseTransport();
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void Failed()
|
||||
{
|
||||
if (!mClosed)
|
||||
{
|
||||
mFailed = true;
|
||||
CloseTransport();
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void Fail(byte alertDescription)
|
||||
{
|
||||
if (!mClosed)
|
||||
{
|
||||
try
|
||||
{
|
||||
RaiseAlert(2, alertDescription, null, null);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
mFailed = true;
|
||||
CloseTransport();
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void Warn(byte alertDescription, string message)
|
||||
{
|
||||
RaiseAlert(1, alertDescription, message, null);
|
||||
}
|
||||
|
||||
private void CloseTransport()
|
||||
{
|
||||
if (mClosed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (!mFailed)
|
||||
{
|
||||
Warn(0, null);
|
||||
}
|
||||
mTransport.Close();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
mClosed = true;
|
||||
}
|
||||
|
||||
private void RaiseAlert(byte alertLevel, byte alertDescription, string message, Exception cause)
|
||||
{
|
||||
mPeer.NotifyAlertRaised(alertLevel, alertDescription, message, cause);
|
||||
SendRecord(21, new byte[2] { alertLevel, alertDescription }, 0, 2);
|
||||
}
|
||||
|
||||
private int ReceiveRecord(byte[] buf, int off, int len, int waitMillis)
|
||||
{
|
||||
if (mRecordQueue.Available > 0)
|
||||
{
|
||||
int num = 0;
|
||||
if (mRecordQueue.Available >= 13)
|
||||
{
|
||||
byte[] buf2 = new byte[2];
|
||||
mRecordQueue.Read(buf2, 0, 2, 11);
|
||||
num = TlsUtilities.ReadUint16(buf2, 0);
|
||||
}
|
||||
int num2 = System.Math.Min(mRecordQueue.Available, 13 + num);
|
||||
mRecordQueue.RemoveData(buf, off, num2, 0);
|
||||
return num2;
|
||||
}
|
||||
int num3 = mTransport.Receive(buf, off, len, waitMillis);
|
||||
if (num3 >= 13)
|
||||
{
|
||||
int num4 = TlsUtilities.ReadUint16(buf, off + 11);
|
||||
int num5 = 13 + num4;
|
||||
if (num3 > num5)
|
||||
{
|
||||
mRecordQueue.AddData(buf, off + num5, num3 - num5);
|
||||
num3 = num5;
|
||||
}
|
||||
}
|
||||
return num3;
|
||||
}
|
||||
|
||||
private void SendRecord(byte contentType, byte[] buf, int off, int len)
|
||||
{
|
||||
if (mWriteVersion != null)
|
||||
{
|
||||
if (len > mPlaintextLimit)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
if (len < 1 && contentType != 23)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
int epoch = mWriteEpoch.Epoch;
|
||||
long num = mWriteEpoch.AllocateSequenceNumber();
|
||||
byte[] array = mWriteEpoch.Cipher.EncodePlaintext(GetMacSequenceNumber(epoch, num), contentType, buf, off, len);
|
||||
byte[] array2 = new byte[array.Length + 13];
|
||||
TlsUtilities.WriteUint8(contentType, array2, 0);
|
||||
ProtocolVersion version = mWriteVersion;
|
||||
TlsUtilities.WriteVersion(version, array2, 1);
|
||||
TlsUtilities.WriteUint16(epoch, array2, 3);
|
||||
TlsUtilities.WriteUint48(num, array2, 5);
|
||||
TlsUtilities.WriteUint16(array.Length, array2, 11);
|
||||
Array.Copy(array, 0, array2, 13, array.Length);
|
||||
mTransport.Send(array2, 0, array2.Length);
|
||||
}
|
||||
}
|
||||
|
||||
private static long GetMacSequenceNumber(int epoch, long sequence_number)
|
||||
{
|
||||
return ((epoch & 0xFFFFFFFFu) << 48) | sequence_number;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal class DtlsReliableHandshake
|
||||
{
|
||||
internal class Message
|
||||
{
|
||||
private readonly int mMessageSeq;
|
||||
|
||||
private readonly byte mMsgType;
|
||||
|
||||
private readonly byte[] mBody;
|
||||
|
||||
public int Seq => mMessageSeq;
|
||||
|
||||
public byte Type => mMsgType;
|
||||
|
||||
public byte[] Body => mBody;
|
||||
|
||||
internal Message(int message_seq, byte msg_type, byte[] body)
|
||||
{
|
||||
mMessageSeq = message_seq;
|
||||
mMsgType = msg_type;
|
||||
mBody = body;
|
||||
}
|
||||
}
|
||||
|
||||
internal class RecordLayerBuffer : MemoryStream
|
||||
{
|
||||
internal RecordLayerBuffer(int size)
|
||||
: base(size)
|
||||
{
|
||||
}
|
||||
|
||||
internal void SendToRecordLayer(DtlsRecordLayer recordLayer)
|
||||
{
|
||||
byte[] buffer = GetBuffer();
|
||||
int len = (int)Length;
|
||||
recordLayer.Send(buffer, 0, len);
|
||||
Platform.Dispose(this);
|
||||
}
|
||||
}
|
||||
|
||||
internal class Retransmit : DtlsHandshakeRetransmit
|
||||
{
|
||||
private readonly DtlsReliableHandshake mOuter;
|
||||
|
||||
internal Retransmit(DtlsReliableHandshake outer)
|
||||
{
|
||||
mOuter = outer;
|
||||
}
|
||||
|
||||
public void ReceivedHandshakeRecord(int epoch, byte[] buf, int off, int len)
|
||||
{
|
||||
mOuter.ProcessRecord(0, epoch, buf, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
private const int MaxReceiveAhead = 16;
|
||||
|
||||
private const int MessageHeaderLength = 12;
|
||||
|
||||
private readonly DtlsRecordLayer mRecordLayer;
|
||||
|
||||
private TlsHandshakeHash mHandshakeHash;
|
||||
|
||||
private IDictionary mCurrentInboundFlight = Platform.CreateHashtable();
|
||||
|
||||
private IDictionary mPreviousInboundFlight = null;
|
||||
|
||||
private IList mOutboundFlight = Platform.CreateArrayList();
|
||||
|
||||
private bool mSending = true;
|
||||
|
||||
private int mMessageSeq = 0;
|
||||
|
||||
private int mNextReceiveSeq = 0;
|
||||
|
||||
internal TlsHandshakeHash HandshakeHash => mHandshakeHash;
|
||||
|
||||
internal DtlsReliableHandshake(TlsContext context, DtlsRecordLayer transport)
|
||||
{
|
||||
mRecordLayer = transport;
|
||||
mHandshakeHash = new DeferredHash();
|
||||
mHandshakeHash.Init(context);
|
||||
}
|
||||
|
||||
internal void NotifyHelloComplete()
|
||||
{
|
||||
mHandshakeHash = mHandshakeHash.NotifyPrfDetermined();
|
||||
}
|
||||
|
||||
internal TlsHandshakeHash PrepareToFinish()
|
||||
{
|
||||
TlsHandshakeHash result = mHandshakeHash;
|
||||
mHandshakeHash = mHandshakeHash.StopTracking();
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void SendMessage(byte msg_type, byte[] body)
|
||||
{
|
||||
TlsUtilities.CheckUint24(body.Length);
|
||||
if (!mSending)
|
||||
{
|
||||
CheckInboundFlight();
|
||||
mSending = true;
|
||||
mOutboundFlight.Clear();
|
||||
}
|
||||
Message message = new Message(mMessageSeq++, msg_type, body);
|
||||
mOutboundFlight.Add(message);
|
||||
WriteMessage(message);
|
||||
UpdateHandshakeMessagesDigest(message);
|
||||
}
|
||||
|
||||
internal byte[] ReceiveMessageBody(byte msg_type)
|
||||
{
|
||||
Message message = ReceiveMessage();
|
||||
if (message.Type != msg_type)
|
||||
{
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
return message.Body;
|
||||
}
|
||||
|
||||
internal Message ReceiveMessage()
|
||||
{
|
||||
if (mSending)
|
||||
{
|
||||
mSending = false;
|
||||
PrepareInboundFlight(Platform.CreateHashtable());
|
||||
}
|
||||
byte[] array = null;
|
||||
int num = 1000;
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Message pendingMessage = GetPendingMessage();
|
||||
if (pendingMessage != null)
|
||||
{
|
||||
return pendingMessage;
|
||||
}
|
||||
int receiveLimit = mRecordLayer.GetReceiveLimit();
|
||||
if (array == null || array.Length < receiveLimit)
|
||||
{
|
||||
array = new byte[receiveLimit];
|
||||
}
|
||||
int num2 = mRecordLayer.Receive(array, 0, receiveLimit, num);
|
||||
if (num2 >= 0)
|
||||
{
|
||||
if (ProcessRecord(16, mRecordLayer.ReadEpoch, array, 0, num2))
|
||||
{
|
||||
num = BackOff(num);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
ResendOutboundFlight();
|
||||
num = BackOff(num);
|
||||
}
|
||||
}
|
||||
|
||||
internal void Finish()
|
||||
{
|
||||
DtlsHandshakeRetransmit retransmit = null;
|
||||
if (!mSending)
|
||||
{
|
||||
CheckInboundFlight();
|
||||
}
|
||||
else
|
||||
{
|
||||
PrepareInboundFlight(null);
|
||||
if (mPreviousInboundFlight != null)
|
||||
{
|
||||
retransmit = new Retransmit(this);
|
||||
}
|
||||
}
|
||||
mRecordLayer.HandshakeSuccessful(retransmit);
|
||||
}
|
||||
|
||||
internal void ResetHandshakeMessagesDigest()
|
||||
{
|
||||
mHandshakeHash.Reset();
|
||||
}
|
||||
|
||||
private int BackOff(int timeoutMillis)
|
||||
{
|
||||
return System.Math.Min(timeoutMillis * 2, 60000);
|
||||
}
|
||||
|
||||
private void CheckInboundFlight()
|
||||
{
|
||||
foreach (object key in mCurrentInboundFlight.Keys)
|
||||
{
|
||||
int num = (int)key;
|
||||
_ = mNextReceiveSeq;
|
||||
}
|
||||
}
|
||||
|
||||
private Message GetPendingMessage()
|
||||
{
|
||||
DtlsReassembler dtlsReassembler = (DtlsReassembler)mCurrentInboundFlight[mNextReceiveSeq];
|
||||
if (dtlsReassembler != null)
|
||||
{
|
||||
byte[] bodyIfComplete = dtlsReassembler.GetBodyIfComplete();
|
||||
if (bodyIfComplete != null)
|
||||
{
|
||||
mPreviousInboundFlight = null;
|
||||
return UpdateHandshakeMessagesDigest(new Message(mNextReceiveSeq++, dtlsReassembler.MsgType, bodyIfComplete));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void PrepareInboundFlight(IDictionary nextFlight)
|
||||
{
|
||||
ResetAll(mCurrentInboundFlight);
|
||||
mPreviousInboundFlight = mCurrentInboundFlight;
|
||||
mCurrentInboundFlight = nextFlight;
|
||||
}
|
||||
|
||||
private bool ProcessRecord(int windowSize, int epoch, byte[] buf, int off, int len)
|
||||
{
|
||||
bool flag = false;
|
||||
while (len >= 12)
|
||||
{
|
||||
int num = TlsUtilities.ReadUint24(buf, off + 9);
|
||||
int num2 = num + 12;
|
||||
if (len < num2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
int num3 = TlsUtilities.ReadUint24(buf, off + 1);
|
||||
int num4 = TlsUtilities.ReadUint24(buf, off + 6);
|
||||
if (num4 + num > num3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
byte b = TlsUtilities.ReadUint8(buf, off);
|
||||
int num5 = ((b == 20) ? 1 : 0);
|
||||
if (epoch != num5)
|
||||
{
|
||||
break;
|
||||
}
|
||||
int num6 = TlsUtilities.ReadUint16(buf, off + 4);
|
||||
if (num6 < mNextReceiveSeq + windowSize)
|
||||
{
|
||||
if (num6 >= mNextReceiveSeq)
|
||||
{
|
||||
DtlsReassembler dtlsReassembler = (DtlsReassembler)mCurrentInboundFlight[num6];
|
||||
if (dtlsReassembler == null)
|
||||
{
|
||||
dtlsReassembler = new DtlsReassembler(b, num3);
|
||||
mCurrentInboundFlight[num6] = dtlsReassembler;
|
||||
}
|
||||
dtlsReassembler.ContributeFragment(b, num3, buf, off + 12, num4, num);
|
||||
}
|
||||
else if (mPreviousInboundFlight != null)
|
||||
{
|
||||
DtlsReassembler dtlsReassembler2 = (DtlsReassembler)mPreviousInboundFlight[num6];
|
||||
if (dtlsReassembler2 != null)
|
||||
{
|
||||
dtlsReassembler2.ContributeFragment(b, num3, buf, off + 12, num4, num);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
off += num2;
|
||||
len -= num2;
|
||||
}
|
||||
bool flag2 = flag && CheckAll(mPreviousInboundFlight);
|
||||
if (flag2)
|
||||
{
|
||||
ResendOutboundFlight();
|
||||
ResetAll(mPreviousInboundFlight);
|
||||
}
|
||||
return flag2;
|
||||
}
|
||||
|
||||
private void ResendOutboundFlight()
|
||||
{
|
||||
mRecordLayer.ResetWriteEpoch();
|
||||
for (int i = 0; i < mOutboundFlight.Count; i++)
|
||||
{
|
||||
WriteMessage((Message)mOutboundFlight[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private Message UpdateHandshakeMessagesDigest(Message message)
|
||||
{
|
||||
if (message.Type != 0)
|
||||
{
|
||||
byte[] body = message.Body;
|
||||
byte[] array = new byte[12];
|
||||
TlsUtilities.WriteUint8(message.Type, array, 0);
|
||||
TlsUtilities.WriteUint24(body.Length, array, 1);
|
||||
TlsUtilities.WriteUint16(message.Seq, array, 4);
|
||||
TlsUtilities.WriteUint24(0, array, 6);
|
||||
TlsUtilities.WriteUint24(body.Length, array, 9);
|
||||
mHandshakeHash.BlockUpdate(array, 0, array.Length);
|
||||
mHandshakeHash.BlockUpdate(body, 0, body.Length);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private void WriteMessage(Message message)
|
||||
{
|
||||
int sendLimit = mRecordLayer.GetSendLimit();
|
||||
int num = sendLimit - 12;
|
||||
if (num < 1)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
int num2 = message.Body.Length;
|
||||
int num3 = 0;
|
||||
do
|
||||
{
|
||||
int num4 = System.Math.Min(num2 - num3, num);
|
||||
WriteHandshakeFragment(message, num3, num4);
|
||||
num3 += num4;
|
||||
}
|
||||
while (num3 < num2);
|
||||
}
|
||||
|
||||
private void WriteHandshakeFragment(Message message, int fragment_offset, int fragment_length)
|
||||
{
|
||||
RecordLayerBuffer recordLayerBuffer = new RecordLayerBuffer(12 + fragment_length);
|
||||
TlsUtilities.WriteUint8(message.Type, recordLayerBuffer);
|
||||
TlsUtilities.WriteUint24(message.Body.Length, recordLayerBuffer);
|
||||
TlsUtilities.WriteUint16(message.Seq, recordLayerBuffer);
|
||||
TlsUtilities.WriteUint24(fragment_offset, recordLayerBuffer);
|
||||
TlsUtilities.WriteUint24(fragment_length, recordLayerBuffer);
|
||||
recordLayerBuffer.Write(message.Body, fragment_offset, fragment_length);
|
||||
recordLayerBuffer.SendToRecordLayer(mRecordLayer);
|
||||
}
|
||||
|
||||
private static bool CheckAll(IDictionary inboundFlight)
|
||||
{
|
||||
foreach (DtlsReassembler value in inboundFlight.Values)
|
||||
{
|
||||
if (value.GetBodyIfComplete() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ResetAll(IDictionary inboundFlight)
|
||||
{
|
||||
foreach (DtlsReassembler value in inboundFlight.Values)
|
||||
{
|
||||
value.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal class DtlsReplayWindow
|
||||
{
|
||||
private const long VALID_SEQ_MASK = 281474976710655L;
|
||||
|
||||
private const long WINDOW_SIZE = 64L;
|
||||
|
||||
private long mLatestConfirmedSeq = -1L;
|
||||
|
||||
private long mBitmap = 0L;
|
||||
|
||||
internal bool ShouldDiscard(long seq)
|
||||
{
|
||||
if ((seq & 0xFFFFFFFFFFFFL) != seq)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (seq <= mLatestConfirmedSeq)
|
||||
{
|
||||
long num = mLatestConfirmedSeq - seq;
|
||||
if (num >= 64)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ((mBitmap & (1L << (int)num)) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void ReportAuthenticated(long seq)
|
||||
{
|
||||
if ((seq & 0xFFFFFFFFFFFFL) != seq)
|
||||
{
|
||||
throw new ArgumentException("out of range", "seq");
|
||||
}
|
||||
if (seq <= mLatestConfirmedSeq)
|
||||
{
|
||||
long num = mLatestConfirmedSeq - seq;
|
||||
if (num < 64)
|
||||
{
|
||||
mBitmap |= 1L << (int)num;
|
||||
}
|
||||
return;
|
||||
}
|
||||
long num2 = seq - mLatestConfirmedSeq;
|
||||
if (num2 >= 64)
|
||||
{
|
||||
mBitmap = 1L;
|
||||
}
|
||||
else
|
||||
{
|
||||
mBitmap <<= (int)num2;
|
||||
mBitmap |= 1L;
|
||||
}
|
||||
mLatestConfirmedSeq = seq;
|
||||
}
|
||||
|
||||
internal void Reset()
|
||||
{
|
||||
mLatestConfirmedSeq = -1L;
|
||||
mBitmap = 0L;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,495 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class DtlsServerProtocol : DtlsProtocol
|
||||
{
|
||||
protected internal class ServerHandshakeState
|
||||
{
|
||||
internal TlsServer server = null;
|
||||
|
||||
internal TlsServerContextImpl serverContext = null;
|
||||
|
||||
internal TlsSession tlsSession = null;
|
||||
|
||||
internal SessionParameters sessionParameters = null;
|
||||
|
||||
internal SessionParameters.Builder sessionParametersBuilder = null;
|
||||
|
||||
internal int[] offeredCipherSuites = null;
|
||||
|
||||
internal byte[] offeredCompressionMethods = null;
|
||||
|
||||
internal IDictionary clientExtensions = null;
|
||||
|
||||
internal IDictionary serverExtensions = null;
|
||||
|
||||
internal bool resumedSession = false;
|
||||
|
||||
internal bool secure_renegotiation = false;
|
||||
|
||||
internal bool allowCertificateStatus = false;
|
||||
|
||||
internal bool expectSessionTicket = false;
|
||||
|
||||
internal TlsKeyExchange keyExchange = null;
|
||||
|
||||
internal TlsCredentials serverCredentials = null;
|
||||
|
||||
internal CertificateRequest certificateRequest = null;
|
||||
|
||||
internal short clientCertificateType = -1;
|
||||
|
||||
internal Certificate clientCertificate = null;
|
||||
}
|
||||
|
||||
protected bool mVerifyRequests = true;
|
||||
|
||||
public virtual bool VerifyRequests
|
||||
{
|
||||
get
|
||||
{
|
||||
return mVerifyRequests;
|
||||
}
|
||||
set
|
||||
{
|
||||
mVerifyRequests = value;
|
||||
}
|
||||
}
|
||||
|
||||
public DtlsServerProtocol(SecureRandom secureRandom)
|
||||
: base(secureRandom)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual DtlsTransport Accept(TlsServer server, DatagramTransport transport)
|
||||
{
|
||||
if (server == null)
|
||||
{
|
||||
throw new ArgumentNullException("server");
|
||||
}
|
||||
if (transport == null)
|
||||
{
|
||||
throw new ArgumentNullException("transport");
|
||||
}
|
||||
SecurityParameters securityParameters = new SecurityParameters();
|
||||
securityParameters.entity = 0;
|
||||
ServerHandshakeState serverHandshakeState = new ServerHandshakeState();
|
||||
serverHandshakeState.server = server;
|
||||
serverHandshakeState.serverContext = new TlsServerContextImpl(mSecureRandom, securityParameters);
|
||||
securityParameters.serverRandom = TlsProtocol.CreateRandomBlock(server.ShouldUseGmtUnixTime(), serverHandshakeState.serverContext.NonceRandomGenerator);
|
||||
server.Init(serverHandshakeState.serverContext);
|
||||
DtlsRecordLayer recordLayer = new DtlsRecordLayer(transport, serverHandshakeState.serverContext, server, 22);
|
||||
try
|
||||
{
|
||||
return ServerHandshake(serverHandshakeState, recordLayer);
|
||||
}
|
||||
catch (TlsFatalAlert tlsFatalAlert)
|
||||
{
|
||||
AbortServerHandshake(serverHandshakeState, recordLayer, tlsFatalAlert.AlertDescription);
|
||||
throw tlsFatalAlert;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
AbortServerHandshake(serverHandshakeState, recordLayer, 80);
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception alertCause)
|
||||
{
|
||||
AbortServerHandshake(serverHandshakeState, recordLayer, 80);
|
||||
throw new TlsFatalAlert(80, alertCause);
|
||||
}
|
||||
finally
|
||||
{
|
||||
securityParameters.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void AbortServerHandshake(ServerHandshakeState state, DtlsRecordLayer recordLayer, byte alertDescription)
|
||||
{
|
||||
recordLayer.Fail(alertDescription);
|
||||
InvalidateSession(state);
|
||||
}
|
||||
|
||||
internal virtual DtlsTransport ServerHandshake(ServerHandshakeState state, DtlsRecordLayer recordLayer)
|
||||
{
|
||||
SecurityParameters securityParameters = state.serverContext.SecurityParameters;
|
||||
DtlsReliableHandshake dtlsReliableHandshake = new DtlsReliableHandshake(state.serverContext, recordLayer);
|
||||
DtlsReliableHandshake.Message message = dtlsReliableHandshake.ReceiveMessage();
|
||||
if (message.Type == 1)
|
||||
{
|
||||
ProcessClientHello(state, message.Body);
|
||||
byte[] body = GenerateServerHello(state);
|
||||
DtlsProtocol.ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.maxFragmentLength);
|
||||
ProtocolVersion writeVersion = (recordLayer.ReadVersion = state.serverContext.ServerVersion);
|
||||
recordLayer.SetWriteVersion(writeVersion);
|
||||
dtlsReliableHandshake.SendMessage(2, body);
|
||||
dtlsReliableHandshake.NotifyHelloComplete();
|
||||
IList serverSupplementalData = state.server.GetServerSupplementalData();
|
||||
if (serverSupplementalData != null)
|
||||
{
|
||||
byte[] body2 = DtlsProtocol.GenerateSupplementalData(serverSupplementalData);
|
||||
dtlsReliableHandshake.SendMessage(23, body2);
|
||||
}
|
||||
state.keyExchange = state.server.GetKeyExchange();
|
||||
state.keyExchange.Init(state.serverContext);
|
||||
state.serverCredentials = state.server.GetCredentials();
|
||||
Certificate certificate = null;
|
||||
if (state.serverCredentials == null)
|
||||
{
|
||||
state.keyExchange.SkipServerCredentials();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.keyExchange.ProcessServerCredentials(state.serverCredentials);
|
||||
certificate = state.serverCredentials.Certificate;
|
||||
byte[] body3 = DtlsProtocol.GenerateCertificate(certificate);
|
||||
dtlsReliableHandshake.SendMessage(11, body3);
|
||||
}
|
||||
if (certificate == null || certificate.IsEmpty)
|
||||
{
|
||||
state.allowCertificateStatus = false;
|
||||
}
|
||||
if (state.allowCertificateStatus)
|
||||
{
|
||||
CertificateStatus certificateStatus = state.server.GetCertificateStatus();
|
||||
if (certificateStatus != null)
|
||||
{
|
||||
byte[] body4 = GenerateCertificateStatus(state, certificateStatus);
|
||||
dtlsReliableHandshake.SendMessage(22, body4);
|
||||
}
|
||||
}
|
||||
byte[] array = state.keyExchange.GenerateServerKeyExchange();
|
||||
if (array != null)
|
||||
{
|
||||
dtlsReliableHandshake.SendMessage(12, array);
|
||||
}
|
||||
if (state.serverCredentials != null)
|
||||
{
|
||||
state.certificateRequest = state.server.GetCertificateRequest();
|
||||
if (state.certificateRequest != null)
|
||||
{
|
||||
if (TlsUtilities.IsTlsV12(state.serverContext) != (state.certificateRequest.SupportedSignatureAlgorithms != null))
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
state.keyExchange.ValidateCertificateRequest(state.certificateRequest);
|
||||
byte[] body5 = GenerateCertificateRequest(state, state.certificateRequest);
|
||||
dtlsReliableHandshake.SendMessage(13, body5);
|
||||
TlsUtilities.TrackHashAlgorithms(dtlsReliableHandshake.HandshakeHash, state.certificateRequest.SupportedSignatureAlgorithms);
|
||||
}
|
||||
}
|
||||
dtlsReliableHandshake.SendMessage(14, TlsUtilities.EmptyBytes);
|
||||
dtlsReliableHandshake.HandshakeHash.SealHashAlgorithms();
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
if (message.Type == 23)
|
||||
{
|
||||
ProcessClientSupplementalData(state, message.Body);
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.server.ProcessClientSupplementalData(null);
|
||||
}
|
||||
if (state.certificateRequest == null)
|
||||
{
|
||||
state.keyExchange.SkipClientCredentials();
|
||||
}
|
||||
else if (message.Type == 11)
|
||||
{
|
||||
ProcessClientCertificate(state, message.Body);
|
||||
message = dtlsReliableHandshake.ReceiveMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TlsUtilities.IsTlsV12(state.serverContext))
|
||||
{
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
NotifyClientCertificate(state, Certificate.EmptyChain);
|
||||
}
|
||||
if (message.Type == 16)
|
||||
{
|
||||
ProcessClientKeyExchange(state, message.Body);
|
||||
TlsHandshakeHash tlsHandshakeHash = dtlsReliableHandshake.PrepareToFinish();
|
||||
securityParameters.sessionHash = TlsProtocol.GetCurrentPrfHash(state.serverContext, tlsHandshakeHash, null);
|
||||
TlsProtocol.EstablishMasterSecret(state.serverContext, state.keyExchange);
|
||||
recordLayer.InitPendingEpoch(state.server.GetCipher());
|
||||
if (ExpectCertificateVerifyMessage(state))
|
||||
{
|
||||
byte[] body6 = dtlsReliableHandshake.ReceiveMessageBody(15);
|
||||
ProcessCertificateVerify(state, body6, tlsHandshakeHash);
|
||||
}
|
||||
byte[] expected_verify_data = TlsUtilities.CalculateVerifyData(state.serverContext, "client finished", TlsProtocol.GetCurrentPrfHash(state.serverContext, dtlsReliableHandshake.HandshakeHash, null));
|
||||
ProcessFinished(dtlsReliableHandshake.ReceiveMessageBody(20), expected_verify_data);
|
||||
if (state.expectSessionTicket)
|
||||
{
|
||||
NewSessionTicket newSessionTicket = state.server.GetNewSessionTicket();
|
||||
byte[] body7 = GenerateNewSessionTicket(state, newSessionTicket);
|
||||
dtlsReliableHandshake.SendMessage(4, body7);
|
||||
}
|
||||
byte[] body8 = TlsUtilities.CalculateVerifyData(state.serverContext, "server finished", TlsProtocol.GetCurrentPrfHash(state.serverContext, dtlsReliableHandshake.HandshakeHash, null));
|
||||
dtlsReliableHandshake.SendMessage(20, body8);
|
||||
dtlsReliableHandshake.Finish();
|
||||
state.server.NotifyHandshakeComplete();
|
||||
return new DtlsTransport(recordLayer);
|
||||
}
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
|
||||
protected virtual void InvalidateSession(ServerHandshakeState state)
|
||||
{
|
||||
if (state.sessionParameters != null)
|
||||
{
|
||||
state.sessionParameters.Clear();
|
||||
state.sessionParameters = null;
|
||||
}
|
||||
if (state.tlsSession != null)
|
||||
{
|
||||
state.tlsSession.Invalidate();
|
||||
state.tlsSession = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual byte[] GenerateCertificateRequest(ServerHandshakeState state, CertificateRequest certificateRequest)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
certificateRequest.Encode(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
protected virtual byte[] GenerateCertificateStatus(ServerHandshakeState state, CertificateStatus certificateStatus)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
certificateStatus.Encode(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
protected virtual byte[] GenerateNewSessionTicket(ServerHandshakeState state, NewSessionTicket newSessionTicket)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
newSessionTicket.Encode(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
protected virtual byte[] GenerateServerHello(ServerHandshakeState state)
|
||||
{
|
||||
SecurityParameters securityParameters = state.serverContext.SecurityParameters;
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
ProtocolVersion serverVersion = state.server.GetServerVersion();
|
||||
if (!serverVersion.IsEqualOrEarlierVersionOf(state.serverContext.ClientVersion))
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
state.serverContext.SetServerVersion(serverVersion);
|
||||
TlsUtilities.WriteVersion(state.serverContext.ServerVersion, memoryStream);
|
||||
memoryStream.Write(securityParameters.ServerRandom, 0, securityParameters.ServerRandom.Length);
|
||||
TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, memoryStream);
|
||||
int selectedCipherSuite = state.server.GetSelectedCipherSuite();
|
||||
if (!Arrays.Contains(state.offeredCipherSuites, selectedCipherSuite) || selectedCipherSuite == 0 || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, state.serverContext.ServerVersion))
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
DtlsProtocol.ValidateSelectedCipherSuite(selectedCipherSuite, 80);
|
||||
securityParameters.cipherSuite = selectedCipherSuite;
|
||||
byte selectedCompressionMethod = state.server.GetSelectedCompressionMethod();
|
||||
if (!Arrays.Contains(state.offeredCompressionMethods, selectedCompressionMethod))
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
securityParameters.compressionAlgorithm = selectedCompressionMethod;
|
||||
TlsUtilities.WriteUint16(selectedCipherSuite, memoryStream);
|
||||
TlsUtilities.WriteUint8(selectedCompressionMethod, memoryStream);
|
||||
state.serverExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(state.server.GetServerExtensions());
|
||||
if (state.secure_renegotiation)
|
||||
{
|
||||
byte[] extensionData = TlsUtilities.GetExtensionData(state.serverExtensions, 65281);
|
||||
if (null == extensionData)
|
||||
{
|
||||
state.serverExtensions[65281] = TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes);
|
||||
}
|
||||
}
|
||||
if (securityParameters.IsExtendedMasterSecret)
|
||||
{
|
||||
TlsExtensionsUtilities.AddExtendedMasterSecretExtension(state.serverExtensions);
|
||||
}
|
||||
if (state.serverExtensions.Count > 0)
|
||||
{
|
||||
securityParameters.encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(state.serverExtensions);
|
||||
securityParameters.maxFragmentLength = DtlsProtocol.EvaluateMaxFragmentLengthExtension(state.resumedSession, state.clientExtensions, state.serverExtensions, 80);
|
||||
securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(state.serverExtensions);
|
||||
state.allowCertificateStatus = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, 5, 80);
|
||||
state.expectSessionTicket = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, 35, 80);
|
||||
TlsProtocol.WriteExtensions(memoryStream, state.serverExtensions);
|
||||
}
|
||||
securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.serverContext, securityParameters.CipherSuite);
|
||||
securityParameters.verifyDataLength = 12;
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
protected virtual void NotifyClientCertificate(ServerHandshakeState state, Certificate clientCertificate)
|
||||
{
|
||||
if (state.certificateRequest == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
if (state.clientCertificate != null)
|
||||
{
|
||||
throw new TlsFatalAlert(10);
|
||||
}
|
||||
state.clientCertificate = clientCertificate;
|
||||
if (clientCertificate.IsEmpty)
|
||||
{
|
||||
state.keyExchange.SkipClientCredentials();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.clientCertificateType = TlsUtilities.GetClientCertificateType(clientCertificate, state.serverCredentials.Certificate);
|
||||
state.keyExchange.ProcessClientCertificate(clientCertificate);
|
||||
}
|
||||
state.server.NotifyClientCertificate(clientCertificate);
|
||||
}
|
||||
|
||||
protected virtual void ProcessClientCertificate(ServerHandshakeState state, byte[] body)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream(body, writable: false);
|
||||
Certificate clientCertificate = Certificate.Parse(memoryStream);
|
||||
TlsProtocol.AssertEmpty(memoryStream);
|
||||
NotifyClientCertificate(state, clientCertificate);
|
||||
}
|
||||
|
||||
protected virtual void ProcessCertificateVerify(ServerHandshakeState state, byte[] body, TlsHandshakeHash prepareFinishHash)
|
||||
{
|
||||
if (state.certificateRequest == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
MemoryStream memoryStream = new MemoryStream(body, writable: false);
|
||||
TlsServerContextImpl serverContext = state.serverContext;
|
||||
DigitallySigned digitallySigned = DigitallySigned.Parse(serverContext, memoryStream);
|
||||
TlsProtocol.AssertEmpty(memoryStream);
|
||||
try
|
||||
{
|
||||
SignatureAndHashAlgorithm algorithm = digitallySigned.Algorithm;
|
||||
byte[] hash;
|
||||
if (TlsUtilities.IsTlsV12(serverContext))
|
||||
{
|
||||
TlsUtilities.VerifySupportedSignatureAlgorithm(state.certificateRequest.SupportedSignatureAlgorithms, algorithm);
|
||||
hash = prepareFinishHash.GetFinalHash(algorithm.Hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
hash = serverContext.SecurityParameters.SessionHash;
|
||||
}
|
||||
X509CertificateStructure certificateAt = state.clientCertificate.GetCertificateAt(0);
|
||||
SubjectPublicKeyInfo subjectPublicKeyInfo = certificateAt.SubjectPublicKeyInfo;
|
||||
AsymmetricKeyParameter publicKey = PublicKeyFactory.CreateKey(subjectPublicKeyInfo);
|
||||
TlsSigner tlsSigner = TlsUtilities.CreateTlsSigner((byte)state.clientCertificateType);
|
||||
tlsSigner.Init(serverContext);
|
||||
if (!tlsSigner.VerifyRawSignature(algorithm, digitallySigned.Signature, publicKey, hash))
|
||||
{
|
||||
throw new TlsFatalAlert(51);
|
||||
}
|
||||
}
|
||||
catch (TlsFatalAlert tlsFatalAlert)
|
||||
{
|
||||
throw tlsFatalAlert;
|
||||
}
|
||||
catch (Exception alertCause)
|
||||
{
|
||||
throw new TlsFatalAlert(51, alertCause);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ProcessClientHello(ServerHandshakeState state, byte[] body)
|
||||
{
|
||||
MemoryStream input = new MemoryStream(body, writable: false);
|
||||
ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(input);
|
||||
if (!protocolVersion.IsDtls)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
byte[] clientRandom = TlsUtilities.ReadFully(32, input);
|
||||
byte[] array = TlsUtilities.ReadOpaque8(input);
|
||||
if (array.Length > 32)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
TlsUtilities.ReadOpaque8(input);
|
||||
int num = TlsUtilities.ReadUint16(input);
|
||||
if (num < 2 || (num & 1) != 0)
|
||||
{
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
state.offeredCipherSuites = TlsUtilities.ReadUint16Array(num / 2, input);
|
||||
int num2 = TlsUtilities.ReadUint8(input);
|
||||
if (num2 < 1)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
state.offeredCompressionMethods = TlsUtilities.ReadUint8Array(num2, input);
|
||||
state.clientExtensions = TlsProtocol.ReadExtensions(input);
|
||||
TlsServerContextImpl serverContext = state.serverContext;
|
||||
SecurityParameters securityParameters = serverContext.SecurityParameters;
|
||||
securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.clientExtensions);
|
||||
if (!securityParameters.IsExtendedMasterSecret && state.server.RequiresExtendedMasterSecret())
|
||||
{
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
serverContext.SetClientVersion(protocolVersion);
|
||||
state.server.NotifyClientVersion(protocolVersion);
|
||||
state.server.NotifyFallback(Arrays.Contains(state.offeredCipherSuites, 22016));
|
||||
securityParameters.clientRandom = clientRandom;
|
||||
state.server.NotifyOfferedCipherSuites(state.offeredCipherSuites);
|
||||
state.server.NotifyOfferedCompressionMethods(state.offeredCompressionMethods);
|
||||
if (Arrays.Contains(state.offeredCipherSuites, 255))
|
||||
{
|
||||
state.secure_renegotiation = true;
|
||||
}
|
||||
byte[] extensionData = TlsUtilities.GetExtensionData(state.clientExtensions, 65281);
|
||||
if (extensionData != null)
|
||||
{
|
||||
state.secure_renegotiation = true;
|
||||
if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
|
||||
{
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
}
|
||||
state.server.NotifySecureRenegotiation(state.secure_renegotiation);
|
||||
if (state.clientExtensions != null)
|
||||
{
|
||||
TlsExtensionsUtilities.GetPaddingExtension(state.clientExtensions);
|
||||
state.server.ProcessClientExtensions(state.clientExtensions);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ProcessClientKeyExchange(ServerHandshakeState state, byte[] body)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream(body, writable: false);
|
||||
state.keyExchange.ProcessClientKeyExchange(memoryStream);
|
||||
TlsProtocol.AssertEmpty(memoryStream);
|
||||
}
|
||||
|
||||
protected virtual void ProcessClientSupplementalData(ServerHandshakeState state, byte[] body)
|
||||
{
|
||||
MemoryStream input = new MemoryStream(body, writable: false);
|
||||
IList clientSupplementalData = TlsProtocol.ReadSupplementalDataMessage(input);
|
||||
state.server.ProcessClientSupplementalData(clientSupplementalData);
|
||||
}
|
||||
|
||||
protected virtual bool ExpectCertificateVerifyMessage(ServerHandshakeState state)
|
||||
{
|
||||
if (state.clientCertificateType >= 0)
|
||||
{
|
||||
return TlsUtilities.HasSigningCapability((byte)state.clientCertificateType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class DtlsTransport : DatagramTransport
|
||||
{
|
||||
private readonly DtlsRecordLayer mRecordLayer;
|
||||
|
||||
internal DtlsTransport(DtlsRecordLayer recordLayer)
|
||||
{
|
||||
mRecordLayer = recordLayer;
|
||||
}
|
||||
|
||||
public virtual int GetReceiveLimit()
|
||||
{
|
||||
return mRecordLayer.GetReceiveLimit();
|
||||
}
|
||||
|
||||
public virtual int GetSendLimit()
|
||||
{
|
||||
return mRecordLayer.GetSendLimit();
|
||||
}
|
||||
|
||||
public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
|
||||
{
|
||||
try
|
||||
{
|
||||
return mRecordLayer.Receive(buf, off, len, waitMillis);
|
||||
}
|
||||
catch (TlsFatalAlert tlsFatalAlert)
|
||||
{
|
||||
mRecordLayer.Fail(tlsFatalAlert.AlertDescription);
|
||||
throw tlsFatalAlert;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
mRecordLayer.Fail(80);
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception alertCause)
|
||||
{
|
||||
mRecordLayer.Fail(80);
|
||||
throw new TlsFatalAlert(80, alertCause);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Send(byte[] buf, int off, int len)
|
||||
{
|
||||
try
|
||||
{
|
||||
mRecordLayer.Send(buf, off, len);
|
||||
}
|
||||
catch (TlsFatalAlert tlsFatalAlert)
|
||||
{
|
||||
mRecordLayer.Fail(tlsFatalAlert.AlertDescription);
|
||||
throw tlsFatalAlert;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
mRecordLayer.Fail(80);
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception alertCause)
|
||||
{
|
||||
mRecordLayer.Fail(80);
|
||||
throw new TlsFatalAlert(80, alertCause);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Close()
|
||||
{
|
||||
mRecordLayer.Close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ECBasisType
|
||||
{
|
||||
public const byte ec_basis_trinomial = 1;
|
||||
|
||||
public const byte ec_basis_pentanomial = 2;
|
||||
|
||||
public static bool IsValid(byte ecBasisType)
|
||||
{
|
||||
if (ecBasisType >= 1)
|
||||
{
|
||||
return ecBasisType <= 2;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ECCurveType
|
||||
{
|
||||
public const byte explicit_prime = 1;
|
||||
|
||||
public const byte explicit_char2 = 2;
|
||||
|
||||
public const byte named_curve = 3;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ECPointFormat
|
||||
{
|
||||
public const byte uncompressed = 0;
|
||||
|
||||
public const byte ansiX962_compressed_prime = 1;
|
||||
|
||||
public const byte ansiX962_compressed_char2 = 2;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class EncryptionAlgorithm
|
||||
{
|
||||
public const int NULL = 0;
|
||||
|
||||
public const int RC4_40 = 1;
|
||||
|
||||
public const int RC4_128 = 2;
|
||||
|
||||
public const int RC2_CBC_40 = 3;
|
||||
|
||||
public const int IDEA_CBC = 4;
|
||||
|
||||
public const int DES40_CBC = 5;
|
||||
|
||||
public const int DES_CBC = 6;
|
||||
|
||||
public const int cls_3DES_EDE_CBC = 7;
|
||||
|
||||
public const int AES_128_CBC = 8;
|
||||
|
||||
public const int AES_256_CBC = 9;
|
||||
|
||||
public const int AES_128_GCM = 10;
|
||||
|
||||
public const int AES_256_GCM = 11;
|
||||
|
||||
public const int CAMELLIA_128_CBC = 12;
|
||||
|
||||
public const int CAMELLIA_256_CBC = 13;
|
||||
|
||||
public const int SEED_CBC = 14;
|
||||
|
||||
public const int AES_128_CCM = 15;
|
||||
|
||||
public const int AES_128_CCM_8 = 16;
|
||||
|
||||
public const int AES_256_CCM = 17;
|
||||
|
||||
public const int AES_256_CCM_8 = 18;
|
||||
|
||||
public const int CAMELLIA_128_GCM = 19;
|
||||
|
||||
public const int CAMELLIA_256_GCM = 20;
|
||||
|
||||
public const int CHACHA20_POLY1305 = 21;
|
||||
|
||||
public const int AES_128_OCB_TAGLEN96 = 103;
|
||||
|
||||
public const int AES_256_OCB_TAGLEN96 = 104;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ExporterLabel
|
||||
{
|
||||
public const string client_finished = "client finished";
|
||||
|
||||
public const string server_finished = "server finished";
|
||||
|
||||
public const string master_secret = "master secret";
|
||||
|
||||
public const string key_expansion = "key expansion";
|
||||
|
||||
public const string client_EAP_encryption = "client EAP encryption";
|
||||
|
||||
public const string ttls_keying_material = "ttls keying material";
|
||||
|
||||
public const string ttls_challenge = "ttls challenge";
|
||||
|
||||
public const string dtls_srtp = "EXTRACTOR-dtls_srtp";
|
||||
|
||||
public static readonly string extended_master_secret = "extended master secret";
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ExtensionType
|
||||
{
|
||||
public const int server_name = 0;
|
||||
|
||||
public const int max_fragment_length = 1;
|
||||
|
||||
public const int client_certificate_url = 2;
|
||||
|
||||
public const int trusted_ca_keys = 3;
|
||||
|
||||
public const int truncated_hmac = 4;
|
||||
|
||||
public const int status_request = 5;
|
||||
|
||||
public const int user_mapping = 6;
|
||||
|
||||
public const int client_authz = 7;
|
||||
|
||||
public const int server_authz = 8;
|
||||
|
||||
public const int cert_type = 9;
|
||||
|
||||
public const int supported_groups = 10;
|
||||
|
||||
[Obsolete("Use 'supported_groups' instead")]
|
||||
public const int elliptic_curves = 10;
|
||||
|
||||
public const int ec_point_formats = 11;
|
||||
|
||||
public const int srp = 12;
|
||||
|
||||
public const int signature_algorithms = 13;
|
||||
|
||||
public const int use_srtp = 14;
|
||||
|
||||
public const int heartbeat = 15;
|
||||
|
||||
public const int application_layer_protocol_negotiation = 16;
|
||||
|
||||
public const int status_request_v2 = 17;
|
||||
|
||||
public const int signed_certificate_timestamp = 18;
|
||||
|
||||
public const int client_certificate_type = 19;
|
||||
|
||||
public const int server_certificate_type = 20;
|
||||
|
||||
public const int padding = 21;
|
||||
|
||||
public const int encrypt_then_mac = 22;
|
||||
|
||||
public const int extended_master_secret = 23;
|
||||
|
||||
public const int cached_info = 25;
|
||||
|
||||
public const int session_ticket = 35;
|
||||
|
||||
public const int renegotiation_info = 65281;
|
||||
|
||||
public static readonly int DRAFT_token_binding = 24;
|
||||
|
||||
public static readonly int negotiated_ff_dhe_groups = 101;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class FiniteFieldDheGroup
|
||||
{
|
||||
public const byte ffdhe2432 = 0;
|
||||
|
||||
public const byte ffdhe3072 = 1;
|
||||
|
||||
public const byte ffdhe4096 = 2;
|
||||
|
||||
public const byte ffdhe6144 = 3;
|
||||
|
||||
public const byte ffdhe8192 = 4;
|
||||
|
||||
public static bool IsValid(byte group)
|
||||
{
|
||||
if (group >= 0)
|
||||
{
|
||||
return group <= 4;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class HandshakeType
|
||||
{
|
||||
public const byte hello_request = 0;
|
||||
|
||||
public const byte client_hello = 1;
|
||||
|
||||
public const byte server_hello = 2;
|
||||
|
||||
public const byte certificate = 11;
|
||||
|
||||
public const byte server_key_exchange = 12;
|
||||
|
||||
public const byte certificate_request = 13;
|
||||
|
||||
public const byte server_hello_done = 14;
|
||||
|
||||
public const byte certificate_verify = 15;
|
||||
|
||||
public const byte client_key_exchange = 16;
|
||||
|
||||
public const byte finished = 20;
|
||||
|
||||
public const byte certificate_url = 21;
|
||||
|
||||
public const byte certificate_status = 22;
|
||||
|
||||
public const byte hello_verify_request = 3;
|
||||
|
||||
public const byte supplemental_data = 23;
|
||||
|
||||
public const byte session_ticket = 4;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class HashAlgorithm
|
||||
{
|
||||
public const byte none = 0;
|
||||
|
||||
public const byte md5 = 1;
|
||||
|
||||
public const byte sha1 = 2;
|
||||
|
||||
public const byte sha224 = 3;
|
||||
|
||||
public const byte sha256 = 4;
|
||||
|
||||
public const byte sha384 = 5;
|
||||
|
||||
public const byte sha512 = 6;
|
||||
|
||||
public static string GetName(byte hashAlgorithm)
|
||||
{
|
||||
return hashAlgorithm switch
|
||||
{
|
||||
0 => "none",
|
||||
1 => "md5",
|
||||
2 => "sha1",
|
||||
3 => "sha224",
|
||||
4 => "sha256",
|
||||
5 => "sha384",
|
||||
6 => "sha512",
|
||||
_ => "UNKNOWN",
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetText(byte hashAlgorithm)
|
||||
{
|
||||
return GetName(hashAlgorithm) + "(" + hashAlgorithm + ")";
|
||||
}
|
||||
|
||||
public static bool IsPrivate(byte hashAlgorithm)
|
||||
{
|
||||
if (224 <= hashAlgorithm)
|
||||
{
|
||||
return hashAlgorithm <= byte.MaxValue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsRecognized(byte hashAlgorithm)
|
||||
{
|
||||
switch (hashAlgorithm)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class HeartbeatExtension
|
||||
{
|
||||
protected readonly byte mMode;
|
||||
|
||||
public virtual byte Mode => mMode;
|
||||
|
||||
public HeartbeatExtension(byte mode)
|
||||
{
|
||||
if (!HeartbeatMode.IsValid(mode))
|
||||
{
|
||||
throw new ArgumentException("not a valid HeartbeatMode value", "mode");
|
||||
}
|
||||
mMode = mode;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
TlsUtilities.WriteUint8(mMode, output);
|
||||
}
|
||||
|
||||
public static HeartbeatExtension Parse(Stream input)
|
||||
{
|
||||
byte b = TlsUtilities.ReadUint8(input);
|
||||
if (!HeartbeatMode.IsValid(b))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
return new HeartbeatExtension(b);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class HeartbeatMessage
|
||||
{
|
||||
internal class PayloadBuffer : MemoryStream
|
||||
{
|
||||
internal byte[] ToTruncatedByteArray(int payloadLength)
|
||||
{
|
||||
int num = payloadLength + 16;
|
||||
if (Length < num)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
byte[] buffer = GetBuffer();
|
||||
return Arrays.CopyOf(buffer, payloadLength);
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly byte mType;
|
||||
|
||||
protected readonly byte[] mPayload;
|
||||
|
||||
protected readonly int mPaddingLength;
|
||||
|
||||
public HeartbeatMessage(byte type, byte[] payload, int paddingLength)
|
||||
{
|
||||
if (!HeartbeatMessageType.IsValid(type))
|
||||
{
|
||||
throw new ArgumentException("not a valid HeartbeatMessageType value", "type");
|
||||
}
|
||||
if (payload == null || payload.Length >= 65536)
|
||||
{
|
||||
throw new ArgumentException("must have length < 2^16", "payload");
|
||||
}
|
||||
if (paddingLength < 16)
|
||||
{
|
||||
throw new ArgumentException("must be at least 16", "paddingLength");
|
||||
}
|
||||
mType = type;
|
||||
mPayload = payload;
|
||||
mPaddingLength = paddingLength;
|
||||
}
|
||||
|
||||
public virtual void Encode(TlsContext context, Stream output)
|
||||
{
|
||||
TlsUtilities.WriteUint8(mType, output);
|
||||
TlsUtilities.CheckUint16(mPayload.Length);
|
||||
TlsUtilities.WriteUint16(mPayload.Length, output);
|
||||
output.Write(mPayload, 0, mPayload.Length);
|
||||
byte[] array = new byte[mPaddingLength];
|
||||
context.NonceRandomGenerator.NextBytes(array);
|
||||
output.Write(array, 0, array.Length);
|
||||
}
|
||||
|
||||
public static HeartbeatMessage Parse(Stream input)
|
||||
{
|
||||
byte b = TlsUtilities.ReadUint8(input);
|
||||
if (!HeartbeatMessageType.IsValid(b))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
int payloadLength = TlsUtilities.ReadUint16(input);
|
||||
PayloadBuffer payloadBuffer = new PayloadBuffer();
|
||||
Streams.PipeAll(input, payloadBuffer);
|
||||
byte[] array = payloadBuffer.ToTruncatedByteArray(payloadLength);
|
||||
if (array == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
TlsUtilities.CheckUint16(payloadBuffer.Length);
|
||||
int paddingLength = (int)payloadBuffer.Length - array.Length;
|
||||
return new HeartbeatMessage(b, array, paddingLength);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class HeartbeatMessageType
|
||||
{
|
||||
public const byte heartbeat_request = 1;
|
||||
|
||||
public const byte heartbeat_response = 2;
|
||||
|
||||
public static bool IsValid(byte heartbeatMessageType)
|
||||
{
|
||||
if (heartbeatMessageType >= 1)
|
||||
{
|
||||
return heartbeatMessageType <= 2;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class HeartbeatMode
|
||||
{
|
||||
public const byte peer_allowed_to_send = 1;
|
||||
|
||||
public const byte peer_not_allowed_to_send = 2;
|
||||
|
||||
public static bool IsValid(byte heartbeatMode)
|
||||
{
|
||||
if (heartbeatMode >= 1)
|
||||
{
|
||||
return heartbeatMode <= 2;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class KeyExchangeAlgorithm
|
||||
{
|
||||
public const int NULL = 0;
|
||||
|
||||
public const int RSA = 1;
|
||||
|
||||
public const int RSA_EXPORT = 2;
|
||||
|
||||
public const int DHE_DSS = 3;
|
||||
|
||||
public const int DHE_DSS_EXPORT = 4;
|
||||
|
||||
public const int DHE_RSA = 5;
|
||||
|
||||
public const int DHE_RSA_EXPORT = 6;
|
||||
|
||||
public const int DH_DSS = 7;
|
||||
|
||||
public const int DH_DSS_EXPORT = 8;
|
||||
|
||||
public const int DH_RSA = 9;
|
||||
|
||||
public const int DH_RSA_EXPORT = 10;
|
||||
|
||||
public const int DH_anon = 11;
|
||||
|
||||
public const int DH_anon_EXPORT = 12;
|
||||
|
||||
public const int PSK = 13;
|
||||
|
||||
public const int DHE_PSK = 14;
|
||||
|
||||
public const int RSA_PSK = 15;
|
||||
|
||||
public const int ECDH_ECDSA = 16;
|
||||
|
||||
public const int ECDHE_ECDSA = 17;
|
||||
|
||||
public const int ECDH_RSA = 18;
|
||||
|
||||
public const int ECDHE_RSA = 19;
|
||||
|
||||
public const int ECDH_anon = 20;
|
||||
|
||||
public const int SRP = 21;
|
||||
|
||||
public const int SRP_DSS = 22;
|
||||
|
||||
public const int SRP_RSA = 23;
|
||||
|
||||
public const int ECDHE_PSK = 24;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class MacAlgorithm
|
||||
{
|
||||
public const int cls_null = 0;
|
||||
|
||||
public const int md5 = 1;
|
||||
|
||||
public const int sha = 2;
|
||||
|
||||
public const int hmac_md5 = 1;
|
||||
|
||||
public const int hmac_sha1 = 2;
|
||||
|
||||
public const int hmac_sha256 = 3;
|
||||
|
||||
public const int hmac_sha384 = 4;
|
||||
|
||||
public const int hmac_sha512 = 5;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class MaxFragmentLength
|
||||
{
|
||||
public const byte pow2_9 = 1;
|
||||
|
||||
public const byte pow2_10 = 2;
|
||||
|
||||
public const byte pow2_11 = 3;
|
||||
|
||||
public const byte pow2_12 = 4;
|
||||
|
||||
public static bool IsValid(byte maxFragmentLength)
|
||||
{
|
||||
if (maxFragmentLength >= 1)
|
||||
{
|
||||
return maxFragmentLength <= 4;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class NameType
|
||||
{
|
||||
public const byte host_name = 0;
|
||||
|
||||
public static bool IsValid(byte nameType)
|
||||
{
|
||||
return nameType == 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class NamedCurve
|
||||
{
|
||||
public const int sect163k1 = 1;
|
||||
|
||||
public const int sect163r1 = 2;
|
||||
|
||||
public const int sect163r2 = 3;
|
||||
|
||||
public const int sect193r1 = 4;
|
||||
|
||||
public const int sect193r2 = 5;
|
||||
|
||||
public const int sect233k1 = 6;
|
||||
|
||||
public const int sect233r1 = 7;
|
||||
|
||||
public const int sect239k1 = 8;
|
||||
|
||||
public const int sect283k1 = 9;
|
||||
|
||||
public const int sect283r1 = 10;
|
||||
|
||||
public const int sect409k1 = 11;
|
||||
|
||||
public const int sect409r1 = 12;
|
||||
|
||||
public const int sect571k1 = 13;
|
||||
|
||||
public const int sect571r1 = 14;
|
||||
|
||||
public const int secp160k1 = 15;
|
||||
|
||||
public const int secp160r1 = 16;
|
||||
|
||||
public const int secp160r2 = 17;
|
||||
|
||||
public const int secp192k1 = 18;
|
||||
|
||||
public const int secp192r1 = 19;
|
||||
|
||||
public const int secp224k1 = 20;
|
||||
|
||||
public const int secp224r1 = 21;
|
||||
|
||||
public const int secp256k1 = 22;
|
||||
|
||||
public const int secp256r1 = 23;
|
||||
|
||||
public const int secp384r1 = 24;
|
||||
|
||||
public const int secp521r1 = 25;
|
||||
|
||||
public const int brainpoolP256r1 = 26;
|
||||
|
||||
public const int brainpoolP384r1 = 27;
|
||||
|
||||
public const int brainpoolP512r1 = 28;
|
||||
|
||||
public const int arbitrary_explicit_prime_curves = 65281;
|
||||
|
||||
public const int arbitrary_explicit_char2_curves = 65282;
|
||||
|
||||
public static bool IsValid(int namedCurve)
|
||||
{
|
||||
if (namedCurve < 1 || namedCurve > 28)
|
||||
{
|
||||
if (namedCurve >= 65281)
|
||||
{
|
||||
return namedCurve <= 65282;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool RefersToASpecificNamedCurve(int namedCurve)
|
||||
{
|
||||
switch (namedCurve)
|
||||
{
|
||||
case 65281:
|
||||
case 65282:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class NewSessionTicket
|
||||
{
|
||||
protected readonly long mTicketLifetimeHint;
|
||||
|
||||
protected readonly byte[] mTicket;
|
||||
|
||||
public virtual long TicketLifetimeHint => mTicketLifetimeHint;
|
||||
|
||||
public virtual byte[] Ticket => mTicket;
|
||||
|
||||
public NewSessionTicket(long ticketLifetimeHint, byte[] ticket)
|
||||
{
|
||||
mTicketLifetimeHint = ticketLifetimeHint;
|
||||
mTicket = ticket;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
TlsUtilities.WriteUint32(mTicketLifetimeHint, output);
|
||||
TlsUtilities.WriteOpaque16(mTicket, output);
|
||||
}
|
||||
|
||||
public static NewSessionTicket Parse(Stream input)
|
||||
{
|
||||
long ticketLifetimeHint = TlsUtilities.ReadUint32(input);
|
||||
byte[] ticket = TlsUtilities.ReadOpaque16(input);
|
||||
return new NewSessionTicket(ticketLifetimeHint, ticket);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Asn1.Ocsp;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class OcspStatusRequest
|
||||
{
|
||||
protected readonly IList mResponderIDList;
|
||||
|
||||
protected readonly X509Extensions mRequestExtensions;
|
||||
|
||||
public virtual IList ResponderIDList => mResponderIDList;
|
||||
|
||||
public virtual X509Extensions RequestExtensions => mRequestExtensions;
|
||||
|
||||
public OcspStatusRequest(IList responderIDList, X509Extensions requestExtensions)
|
||||
{
|
||||
mResponderIDList = responderIDList;
|
||||
mRequestExtensions = requestExtensions;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
if (mResponderIDList == null || mResponderIDList.Count < 1)
|
||||
{
|
||||
TlsUtilities.WriteUint16(0, output);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
for (int i = 0; i < mResponderIDList.Count; i++)
|
||||
{
|
||||
ResponderID responderID = (ResponderID)mResponderIDList[i];
|
||||
byte[] encoded = responderID.GetEncoded("DER");
|
||||
TlsUtilities.WriteOpaque16(encoded, memoryStream);
|
||||
}
|
||||
TlsUtilities.CheckUint16(memoryStream.Length);
|
||||
TlsUtilities.WriteUint16((int)memoryStream.Length, output);
|
||||
Streams.WriteBufTo(memoryStream, output);
|
||||
}
|
||||
if (mRequestExtensions == null)
|
||||
{
|
||||
TlsUtilities.WriteUint16(0, output);
|
||||
return;
|
||||
}
|
||||
byte[] encoded2 = mRequestExtensions.GetEncoded("DER");
|
||||
TlsUtilities.CheckUint16(encoded2.Length);
|
||||
TlsUtilities.WriteUint16(encoded2.Length, output);
|
||||
output.Write(encoded2, 0, encoded2.Length);
|
||||
}
|
||||
|
||||
public static OcspStatusRequest Parse(Stream input)
|
||||
{
|
||||
IList list = Platform.CreateArrayList();
|
||||
int num = TlsUtilities.ReadUint16(input);
|
||||
if (num > 0)
|
||||
{
|
||||
byte[] buffer = TlsUtilities.ReadFully(num, input);
|
||||
MemoryStream memoryStream = new MemoryStream(buffer, writable: false);
|
||||
do
|
||||
{
|
||||
byte[] encoding = TlsUtilities.ReadOpaque16(memoryStream);
|
||||
ResponderID instance = ResponderID.GetInstance(TlsUtilities.ReadDerObject(encoding));
|
||||
list.Add(instance);
|
||||
}
|
||||
while (memoryStream.Position < memoryStream.Length);
|
||||
}
|
||||
X509Extensions requestExtensions = null;
|
||||
int num2 = TlsUtilities.ReadUint16(input);
|
||||
if (num2 > 0)
|
||||
{
|
||||
byte[] encoding2 = TlsUtilities.ReadFully(num2, input);
|
||||
requestExtensions = X509Extensions.GetInstance(TlsUtilities.ReadDerObject(encoding2));
|
||||
}
|
||||
return new OcspStatusRequest(list, requestExtensions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class PrfAlgorithm
|
||||
{
|
||||
public const int tls_prf_legacy = 0;
|
||||
|
||||
public const int tls_prf_sha256 = 1;
|
||||
|
||||
public const int tls_prf_sha384 = 2;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public sealed class ProtocolVersion
|
||||
{
|
||||
public static readonly ProtocolVersion SSLv3 = new ProtocolVersion(768, "SSL 3.0");
|
||||
|
||||
public static readonly ProtocolVersion TLSv10 = new ProtocolVersion(769, "TLS 1.0");
|
||||
|
||||
public static readonly ProtocolVersion TLSv11 = new ProtocolVersion(770, "TLS 1.1");
|
||||
|
||||
public static readonly ProtocolVersion TLSv12 = new ProtocolVersion(771, "TLS 1.2");
|
||||
|
||||
public static readonly ProtocolVersion DTLSv10 = new ProtocolVersion(65279, "DTLS 1.0");
|
||||
|
||||
public static readonly ProtocolVersion DTLSv12 = new ProtocolVersion(65277, "DTLS 1.2");
|
||||
|
||||
private readonly int version;
|
||||
|
||||
private readonly string name;
|
||||
|
||||
public int FullVersion => version;
|
||||
|
||||
public int MajorVersion => version >> 8;
|
||||
|
||||
public int MinorVersion => version & 0xFF;
|
||||
|
||||
public bool IsDtls => MajorVersion == 254;
|
||||
|
||||
public bool IsSsl => this == SSLv3;
|
||||
|
||||
public bool IsTls => MajorVersion == 3;
|
||||
|
||||
private ProtocolVersion(int v, string name)
|
||||
{
|
||||
version = v & 0xFFFF;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public ProtocolVersion GetEquivalentTLSVersion()
|
||||
{
|
||||
if (!IsDtls)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
if (this == DTLSv10)
|
||||
{
|
||||
return TLSv11;
|
||||
}
|
||||
return TLSv12;
|
||||
}
|
||||
|
||||
public bool IsEqualOrEarlierVersionOf(ProtocolVersion version)
|
||||
{
|
||||
if (MajorVersion != version.MajorVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int num = version.MinorVersion - MinorVersion;
|
||||
if (!IsDtls)
|
||||
{
|
||||
return num >= 0;
|
||||
}
|
||||
return num <= 0;
|
||||
}
|
||||
|
||||
public bool IsLaterVersionOf(ProtocolVersion version)
|
||||
{
|
||||
if (MajorVersion != version.MajorVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int num = version.MinorVersion - MinorVersion;
|
||||
if (!IsDtls)
|
||||
{
|
||||
return num < 0;
|
||||
}
|
||||
return num > 0;
|
||||
}
|
||||
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (this != other)
|
||||
{
|
||||
if (other is ProtocolVersion)
|
||||
{
|
||||
return Equals((ProtocolVersion)other);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Equals(ProtocolVersion other)
|
||||
{
|
||||
if (other != null)
|
||||
{
|
||||
return version == other.version;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
public static ProtocolVersion Get(int major, int minor)
|
||||
{
|
||||
return major switch
|
||||
{
|
||||
3 => minor switch
|
||||
{
|
||||
0 => SSLv3,
|
||||
1 => TLSv10,
|
||||
2 => TLSv11,
|
||||
3 => TLSv12,
|
||||
_ => GetUnknownVersion(major, minor, "TLS"),
|
||||
},
|
||||
254 => minor switch
|
||||
{
|
||||
255 => DTLSv10,
|
||||
254 => throw new TlsFatalAlert(47),
|
||||
253 => DTLSv12,
|
||||
_ => GetUnknownVersion(major, minor, "DTLS"),
|
||||
},
|
||||
_ => throw new TlsFatalAlert(47),
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
private static ProtocolVersion GetUnknownVersion(int major, int minor, string prefix)
|
||||
{
|
||||
TlsUtilities.CheckUint8(major);
|
||||
TlsUtilities.CheckUint8(minor);
|
||||
int num = (major << 8) | minor;
|
||||
string text = Platform.ToUpperInvariant(Convert.ToString(0x10000 | num, 16).Substring(1));
|
||||
return new ProtocolVersion(num, prefix + " 0x" + text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class PskTlsClient : AbstractTlsClient
|
||||
{
|
||||
protected TlsDHVerifier mDHVerifier;
|
||||
|
||||
protected TlsPskIdentity mPskIdentity;
|
||||
|
||||
public PskTlsClient(TlsPskIdentity pskIdentity)
|
||||
: this(new DefaultTlsCipherFactory(), pskIdentity)
|
||||
{
|
||||
}
|
||||
|
||||
public PskTlsClient(TlsCipherFactory cipherFactory, TlsPskIdentity pskIdentity)
|
||||
: this(cipherFactory, new DefaultTlsDHVerifier(), pskIdentity)
|
||||
{
|
||||
}
|
||||
|
||||
public PskTlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier, TlsPskIdentity pskIdentity)
|
||||
: base(cipherFactory)
|
||||
{
|
||||
mDHVerifier = dhVerifier;
|
||||
mPskIdentity = pskIdentity;
|
||||
}
|
||||
|
||||
public override int[] GetCipherSuites()
|
||||
{
|
||||
return new int[2] { 49207, 49205 };
|
||||
}
|
||||
|
||||
public override TlsKeyExchange GetKeyExchange()
|
||||
{
|
||||
int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
|
||||
switch (keyExchangeAlgorithm)
|
||||
{
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 24:
|
||||
return CreatePskKeyExchange(keyExchangeAlgorithm);
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
}
|
||||
|
||||
public override TlsAuthentication GetAuthentication()
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, mDHVerifier, null, mNamedCurves, mClientECPointFormats, mServerECPointFormats);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using Org.BouncyCastle.Crypto.Agreement;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class PskTlsServer : AbstractTlsServer
|
||||
{
|
||||
protected TlsPskIdentityManager mPskIdentityManager;
|
||||
|
||||
public PskTlsServer(TlsPskIdentityManager pskIdentityManager)
|
||||
: this(new DefaultTlsCipherFactory(), pskIdentityManager)
|
||||
{
|
||||
}
|
||||
|
||||
public PskTlsServer(TlsCipherFactory cipherFactory, TlsPskIdentityManager pskIdentityManager)
|
||||
: base(cipherFactory)
|
||||
{
|
||||
mPskIdentityManager = pskIdentityManager;
|
||||
}
|
||||
|
||||
protected virtual TlsEncryptionCredentials GetRsaEncryptionCredentials()
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
protected virtual DHParameters GetDHParameters()
|
||||
{
|
||||
return DHStandardGroups.rfc7919_ffdhe2048;
|
||||
}
|
||||
|
||||
protected override int[] GetCipherSuites()
|
||||
{
|
||||
return new int[4] { 49207, 49205, 178, 144 };
|
||||
}
|
||||
|
||||
public override TlsCredentials GetCredentials()
|
||||
{
|
||||
switch (TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite))
|
||||
{
|
||||
case 13:
|
||||
case 14:
|
||||
case 24:
|
||||
return null;
|
||||
case 15:
|
||||
return GetRsaEncryptionCredentials();
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
}
|
||||
|
||||
public override TlsKeyExchange GetKeyExchange()
|
||||
{
|
||||
int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
|
||||
switch (keyExchangeAlgorithm)
|
||||
{
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 24:
|
||||
return CreatePskKeyExchange(keyExchangeAlgorithm);
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, mPskIdentityManager, null, GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal class RecordStream
|
||||
{
|
||||
private class HandshakeHashUpdateStream : BaseOutputStream
|
||||
{
|
||||
private readonly RecordStream mOuter;
|
||||
|
||||
public HandshakeHashUpdateStream(RecordStream mOuter)
|
||||
{
|
||||
this.mOuter = mOuter;
|
||||
}
|
||||
|
||||
public override void Write(byte[] buf, int off, int len)
|
||||
{
|
||||
mOuter.mHandshakeHash.BlockUpdate(buf, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
private class SequenceNumber
|
||||
{
|
||||
private long value = 0L;
|
||||
|
||||
private bool exhausted = false;
|
||||
|
||||
internal long NextValue(byte alertDescription)
|
||||
{
|
||||
if (exhausted)
|
||||
{
|
||||
throw new TlsFatalAlert(alertDescription);
|
||||
}
|
||||
long result = value;
|
||||
if (++value == 0)
|
||||
{
|
||||
exhausted = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private const int DEFAULT_PLAINTEXT_LIMIT = 16384;
|
||||
|
||||
internal const int TLS_HEADER_SIZE = 5;
|
||||
|
||||
internal const int TLS_HEADER_TYPE_OFFSET = 0;
|
||||
|
||||
internal const int TLS_HEADER_VERSION_OFFSET = 1;
|
||||
|
||||
internal const int TLS_HEADER_LENGTH_OFFSET = 3;
|
||||
|
||||
private TlsProtocol mHandler;
|
||||
|
||||
private Stream mInput;
|
||||
|
||||
private Stream mOutput;
|
||||
|
||||
private TlsCompression mPendingCompression = null;
|
||||
|
||||
private TlsCompression mReadCompression = null;
|
||||
|
||||
private TlsCompression mWriteCompression = null;
|
||||
|
||||
private TlsCipher mPendingCipher = null;
|
||||
|
||||
private TlsCipher mReadCipher = null;
|
||||
|
||||
private TlsCipher mWriteCipher = null;
|
||||
|
||||
private SequenceNumber mReadSeqNo = new SequenceNumber();
|
||||
|
||||
private SequenceNumber mWriteSeqNo = new SequenceNumber();
|
||||
|
||||
private MemoryStream mBuffer = new MemoryStream();
|
||||
|
||||
private TlsHandshakeHash mHandshakeHash = null;
|
||||
|
||||
private readonly BaseOutputStream mHandshakeHashUpdater;
|
||||
|
||||
private ProtocolVersion mReadVersion = null;
|
||||
|
||||
private ProtocolVersion mWriteVersion = null;
|
||||
|
||||
private bool mRestrictReadVersion = true;
|
||||
|
||||
private int mPlaintextLimit;
|
||||
|
||||
private int mCompressedLimit;
|
||||
|
||||
private int mCiphertextLimit;
|
||||
|
||||
internal virtual ProtocolVersion ReadVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return mReadVersion;
|
||||
}
|
||||
set
|
||||
{
|
||||
mReadVersion = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual TlsHandshakeHash HandshakeHash => mHandshakeHash;
|
||||
|
||||
internal virtual Stream HandshakeHashUpdater => mHandshakeHashUpdater;
|
||||
|
||||
internal RecordStream(TlsProtocol handler, Stream input, Stream output)
|
||||
{
|
||||
mHandler = handler;
|
||||
mInput = input;
|
||||
mOutput = output;
|
||||
mReadCompression = new TlsNullCompression();
|
||||
mWriteCompression = mReadCompression;
|
||||
mHandshakeHashUpdater = new HandshakeHashUpdateStream(this);
|
||||
}
|
||||
|
||||
internal virtual void Init(TlsContext context)
|
||||
{
|
||||
mReadCipher = new TlsNullCipher(context);
|
||||
mWriteCipher = mReadCipher;
|
||||
mHandshakeHash = new DeferredHash();
|
||||
mHandshakeHash.Init(context);
|
||||
SetPlaintextLimit(16384);
|
||||
}
|
||||
|
||||
internal virtual int GetPlaintextLimit()
|
||||
{
|
||||
return mPlaintextLimit;
|
||||
}
|
||||
|
||||
internal virtual void SetPlaintextLimit(int plaintextLimit)
|
||||
{
|
||||
mPlaintextLimit = plaintextLimit;
|
||||
mCompressedLimit = mPlaintextLimit + 1024;
|
||||
mCiphertextLimit = mCompressedLimit + 1024;
|
||||
}
|
||||
|
||||
internal virtual void SetWriteVersion(ProtocolVersion writeVersion)
|
||||
{
|
||||
mWriteVersion = writeVersion;
|
||||
}
|
||||
|
||||
internal virtual void SetRestrictReadVersion(bool enabled)
|
||||
{
|
||||
mRestrictReadVersion = enabled;
|
||||
}
|
||||
|
||||
internal virtual void SetPendingConnectionState(TlsCompression tlsCompression, TlsCipher tlsCipher)
|
||||
{
|
||||
mPendingCompression = tlsCompression;
|
||||
mPendingCipher = tlsCipher;
|
||||
}
|
||||
|
||||
internal virtual void SentWriteCipherSpec()
|
||||
{
|
||||
if (mPendingCompression == null || mPendingCipher == null)
|
||||
{
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
mWriteCompression = mPendingCompression;
|
||||
mWriteCipher = mPendingCipher;
|
||||
mWriteSeqNo = new SequenceNumber();
|
||||
}
|
||||
|
||||
internal virtual void ReceivedReadCipherSpec()
|
||||
{
|
||||
if (mPendingCompression == null || mPendingCipher == null)
|
||||
{
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
mReadCompression = mPendingCompression;
|
||||
mReadCipher = mPendingCipher;
|
||||
mReadSeqNo = new SequenceNumber();
|
||||
}
|
||||
|
||||
internal virtual void FinaliseHandshake()
|
||||
{
|
||||
if (mReadCompression != mPendingCompression || mWriteCompression != mPendingCompression || mReadCipher != mPendingCipher || mWriteCipher != mPendingCipher)
|
||||
{
|
||||
throw new TlsFatalAlert(40);
|
||||
}
|
||||
mPendingCompression = null;
|
||||
mPendingCipher = null;
|
||||
}
|
||||
|
||||
internal virtual void CheckRecordHeader(byte[] recordHeader)
|
||||
{
|
||||
byte type = TlsUtilities.ReadUint8(recordHeader, 0);
|
||||
CheckType(type, 10);
|
||||
if (!mRestrictReadVersion)
|
||||
{
|
||||
int num = TlsUtilities.ReadVersionRaw(recordHeader, 1);
|
||||
if ((num & 0xFFFFFF00u) != 768)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(recordHeader, 1);
|
||||
if (mReadVersion != null && !protocolVersion.Equals(mReadVersion))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
}
|
||||
int length = TlsUtilities.ReadUint16(recordHeader, 3);
|
||||
CheckLength(length, mCiphertextLimit, 22);
|
||||
}
|
||||
|
||||
internal virtual bool ReadRecord()
|
||||
{
|
||||
byte[] array = TlsUtilities.ReadAllOrNothing(5, mInput);
|
||||
if (array == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byte b = TlsUtilities.ReadUint8(array, 0);
|
||||
CheckType(b, 10);
|
||||
if (!mRestrictReadVersion)
|
||||
{
|
||||
int num = TlsUtilities.ReadVersionRaw(array, 1);
|
||||
if ((num & 0xFFFFFF00u) != 768)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(array, 1);
|
||||
if (mReadVersion == null)
|
||||
{
|
||||
mReadVersion = protocolVersion;
|
||||
}
|
||||
else if (!protocolVersion.Equals(mReadVersion))
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
}
|
||||
int num2 = TlsUtilities.ReadUint16(array, 3);
|
||||
CheckLength(num2, mCiphertextLimit, 22);
|
||||
byte[] array2 = DecodeAndVerify(b, mInput, num2);
|
||||
mHandler.ProcessRecord(b, array2, 0, array2.Length);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal virtual byte[] DecodeAndVerify(byte type, Stream input, int len)
|
||||
{
|
||||
byte[] array = TlsUtilities.ReadFully(len, input);
|
||||
long seqNo = mReadSeqNo.NextValue(10);
|
||||
byte[] array2 = mReadCipher.DecodeCiphertext(seqNo, type, array, 0, array.Length);
|
||||
CheckLength(array2.Length, mCompressedLimit, 22);
|
||||
Stream stream = mReadCompression.Decompress(mBuffer);
|
||||
if (stream != mBuffer)
|
||||
{
|
||||
stream.Write(array2, 0, array2.Length);
|
||||
stream.Flush();
|
||||
array2 = GetBufferContents();
|
||||
}
|
||||
CheckLength(array2.Length, mPlaintextLimit, 30);
|
||||
if (array2.Length < 1 && type != 23)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
return array2;
|
||||
}
|
||||
|
||||
internal virtual void WriteRecord(byte type, byte[] plaintext, int plaintextOffset, int plaintextLength)
|
||||
{
|
||||
if (mWriteVersion != null)
|
||||
{
|
||||
CheckType(type, 80);
|
||||
CheckLength(plaintextLength, mPlaintextLimit, 80);
|
||||
if (plaintextLength < 1 && type != 23)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
Stream stream = mWriteCompression.Compress(mBuffer);
|
||||
long seqNo = mWriteSeqNo.NextValue(80);
|
||||
byte[] array;
|
||||
if (stream == mBuffer)
|
||||
{
|
||||
array = mWriteCipher.EncodePlaintext(seqNo, type, plaintext, plaintextOffset, plaintextLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.Write(plaintext, plaintextOffset, plaintextLength);
|
||||
stream.Flush();
|
||||
byte[] bufferContents = GetBufferContents();
|
||||
CheckLength(bufferContents.Length, plaintextLength + 1024, 80);
|
||||
array = mWriteCipher.EncodePlaintext(seqNo, type, bufferContents, 0, bufferContents.Length);
|
||||
}
|
||||
CheckLength(array.Length, mCiphertextLimit, 80);
|
||||
byte[] array2 = new byte[array.Length + 5];
|
||||
TlsUtilities.WriteUint8(type, array2, 0);
|
||||
TlsUtilities.WriteVersion(mWriteVersion, array2, 1);
|
||||
TlsUtilities.WriteUint16(array.Length, array2, 3);
|
||||
Array.Copy(array, 0, array2, 5, array.Length);
|
||||
mOutput.Write(array2, 0, array2.Length);
|
||||
mOutput.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void NotifyHelloComplete()
|
||||
{
|
||||
mHandshakeHash = mHandshakeHash.NotifyPrfDetermined();
|
||||
}
|
||||
|
||||
internal virtual TlsHandshakeHash PrepareToFinish()
|
||||
{
|
||||
TlsHandshakeHash result = mHandshakeHash;
|
||||
mHandshakeHash = mHandshakeHash.StopTracking();
|
||||
return result;
|
||||
}
|
||||
|
||||
internal virtual void SafeClose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Platform.Dispose(mInput);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
Platform.Dispose(mOutput);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void Flush()
|
||||
{
|
||||
mOutput.Flush();
|
||||
}
|
||||
|
||||
private byte[] GetBufferContents()
|
||||
{
|
||||
byte[] result = mBuffer.ToArray();
|
||||
mBuffer.SetLength(0L);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void CheckType(byte type, byte alertDescription)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
return;
|
||||
}
|
||||
throw new TlsFatalAlert(alertDescription);
|
||||
}
|
||||
|
||||
private static void CheckLength(int length, int limit, byte alertDescription)
|
||||
{
|
||||
if (length > limit)
|
||||
{
|
||||
throw new TlsFatalAlert(alertDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class SecurityParameters
|
||||
{
|
||||
internal int entity = -1;
|
||||
|
||||
internal int cipherSuite = -1;
|
||||
|
||||
internal byte compressionAlgorithm = 0;
|
||||
|
||||
internal int prfAlgorithm = -1;
|
||||
|
||||
internal int verifyDataLength = -1;
|
||||
|
||||
internal byte[] masterSecret = null;
|
||||
|
||||
internal byte[] clientRandom = null;
|
||||
|
||||
internal byte[] serverRandom = null;
|
||||
|
||||
internal byte[] sessionHash = null;
|
||||
|
||||
internal byte[] pskIdentity = null;
|
||||
|
||||
internal byte[] srpIdentity = null;
|
||||
|
||||
internal short maxFragmentLength = -1;
|
||||
|
||||
internal bool truncatedHMac = false;
|
||||
|
||||
internal bool encryptThenMac = false;
|
||||
|
||||
internal bool extendedMasterSecret = false;
|
||||
|
||||
public virtual int Entity => entity;
|
||||
|
||||
public virtual int CipherSuite => cipherSuite;
|
||||
|
||||
public virtual byte CompressionAlgorithm => compressionAlgorithm;
|
||||
|
||||
public virtual int PrfAlgorithm => prfAlgorithm;
|
||||
|
||||
public virtual int VerifyDataLength => verifyDataLength;
|
||||
|
||||
public virtual byte[] MasterSecret => masterSecret;
|
||||
|
||||
public virtual byte[] ClientRandom => clientRandom;
|
||||
|
||||
public virtual byte[] ServerRandom => serverRandom;
|
||||
|
||||
public virtual byte[] SessionHash => sessionHash;
|
||||
|
||||
public virtual byte[] PskIdentity => pskIdentity;
|
||||
|
||||
public virtual byte[] SrpIdentity => srpIdentity;
|
||||
|
||||
public virtual bool IsExtendedMasterSecret => extendedMasterSecret;
|
||||
|
||||
internal virtual void Clear()
|
||||
{
|
||||
if (masterSecret != null)
|
||||
{
|
||||
Arrays.Fill(masterSecret, 0);
|
||||
masterSecret = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class ServerName
|
||||
{
|
||||
protected readonly byte mNameType;
|
||||
|
||||
protected readonly object mName;
|
||||
|
||||
public virtual byte NameType => mNameType;
|
||||
|
||||
public virtual object Name => mName;
|
||||
|
||||
public ServerName(byte nameType, object name)
|
||||
{
|
||||
if (!IsCorrectType(nameType, name))
|
||||
{
|
||||
throw new ArgumentException("not an instance of the correct type", "name");
|
||||
}
|
||||
mNameType = nameType;
|
||||
mName = name;
|
||||
}
|
||||
|
||||
public virtual string GetHostName()
|
||||
{
|
||||
if (!IsCorrectType(0, mName))
|
||||
{
|
||||
throw new InvalidOperationException("'name' is not a HostName string");
|
||||
}
|
||||
return (string)mName;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
TlsUtilities.WriteUint8(mNameType, output);
|
||||
if (mNameType == 0)
|
||||
{
|
||||
byte[] array = Strings.ToAsciiByteArray((string)mName);
|
||||
if (array.Length < 1)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
TlsUtilities.WriteOpaque16(array, output);
|
||||
return;
|
||||
}
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
public static ServerName Parse(Stream input)
|
||||
{
|
||||
byte b = TlsUtilities.ReadUint8(input);
|
||||
if (b == 0)
|
||||
{
|
||||
byte[] array = TlsUtilities.ReadOpaque16(input);
|
||||
if (array.Length < 1)
|
||||
{
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
object name = Strings.FromAsciiByteArray(array);
|
||||
return new ServerName(b, name);
|
||||
}
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
|
||||
protected static bool IsCorrectType(byte nameType, object name)
|
||||
{
|
||||
if (nameType == 0)
|
||||
{
|
||||
return name is string;
|
||||
}
|
||||
throw new ArgumentException("unsupported NameType", "nameType");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class ServerNameList
|
||||
{
|
||||
protected readonly IList mServerNameList;
|
||||
|
||||
public virtual IList ServerNames => mServerNameList;
|
||||
|
||||
public ServerNameList(IList serverNameList)
|
||||
{
|
||||
if (serverNameList == null)
|
||||
{
|
||||
throw new ArgumentNullException("serverNameList");
|
||||
}
|
||||
mServerNameList = serverNameList;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
byte[] array = TlsUtilities.EmptyBytes;
|
||||
foreach (ServerName serverName in ServerNames)
|
||||
{
|
||||
array = CheckNameType(array, serverName.NameType);
|
||||
if (array == null)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
serverName.Encode(memoryStream);
|
||||
}
|
||||
TlsUtilities.CheckUint16(memoryStream.Length);
|
||||
TlsUtilities.WriteUint16((int)memoryStream.Length, output);
|
||||
Streams.WriteBufTo(memoryStream, output);
|
||||
}
|
||||
|
||||
public static ServerNameList Parse(Stream input)
|
||||
{
|
||||
int num = TlsUtilities.ReadUint16(input);
|
||||
if (num < 1)
|
||||
{
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
byte[] buffer = TlsUtilities.ReadFully(num, input);
|
||||
MemoryStream memoryStream = new MemoryStream(buffer, writable: false);
|
||||
byte[] array = TlsUtilities.EmptyBytes;
|
||||
IList list = Platform.CreateArrayList();
|
||||
while (memoryStream.Position < memoryStream.Length)
|
||||
{
|
||||
ServerName serverName = ServerName.Parse(memoryStream);
|
||||
array = CheckNameType(array, serverName.NameType);
|
||||
if (array == null)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
list.Add(serverName);
|
||||
}
|
||||
return new ServerNameList(list);
|
||||
}
|
||||
|
||||
private static byte[] CheckNameType(byte[] nameTypesSeen, byte nameType)
|
||||
{
|
||||
if (!NameType.IsValid(nameType) || Arrays.Contains(nameTypesSeen, nameType))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return Arrays.Append(nameTypesSeen, nameType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class ServerOnlyTlsAuthentication : TlsAuthentication
|
||||
{
|
||||
public abstract void NotifyServerCertificate(Certificate serverCertificate);
|
||||
|
||||
public TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class ServerSrpParams
|
||||
{
|
||||
protected BigInteger m_N;
|
||||
|
||||
protected BigInteger m_g;
|
||||
|
||||
protected BigInteger m_B;
|
||||
|
||||
protected byte[] m_s;
|
||||
|
||||
public virtual BigInteger B => m_B;
|
||||
|
||||
public virtual BigInteger G => m_g;
|
||||
|
||||
public virtual BigInteger N => m_N;
|
||||
|
||||
public virtual byte[] S => m_s;
|
||||
|
||||
public ServerSrpParams(BigInteger N, BigInteger g, byte[] s, BigInteger B)
|
||||
{
|
||||
m_N = N;
|
||||
m_g = g;
|
||||
m_s = Arrays.Clone(s);
|
||||
m_B = B;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
TlsSrpUtilities.WriteSrpParameter(m_N, output);
|
||||
TlsSrpUtilities.WriteSrpParameter(m_g, output);
|
||||
TlsUtilities.WriteOpaque8(m_s, output);
|
||||
TlsSrpUtilities.WriteSrpParameter(m_B, output);
|
||||
}
|
||||
|
||||
public static ServerSrpParams Parse(Stream input)
|
||||
{
|
||||
BigInteger n = TlsSrpUtilities.ReadSrpParameter(input);
|
||||
BigInteger g = TlsSrpUtilities.ReadSrpParameter(input);
|
||||
byte[] s = TlsUtilities.ReadOpaque8(input);
|
||||
BigInteger b = TlsSrpUtilities.ReadSrpParameter(input);
|
||||
return new ServerSrpParams(n, g, s, b);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public sealed class SessionParameters
|
||||
{
|
||||
public sealed class Builder
|
||||
{
|
||||
private int mCipherSuite = -1;
|
||||
|
||||
private short mCompressionAlgorithm = -1;
|
||||
|
||||
private byte[] mMasterSecret = null;
|
||||
|
||||
private Certificate mPeerCertificate = null;
|
||||
|
||||
private byte[] mPskIdentity = null;
|
||||
|
||||
private byte[] mSrpIdentity = null;
|
||||
|
||||
private byte[] mEncodedServerExtensions = null;
|
||||
|
||||
private bool mExtendedMasterSecret = false;
|
||||
|
||||
public SessionParameters Build()
|
||||
{
|
||||
Validate(mCipherSuite >= 0, "cipherSuite");
|
||||
Validate(mCompressionAlgorithm >= 0, "compressionAlgorithm");
|
||||
Validate(mMasterSecret != null, "masterSecret");
|
||||
return new SessionParameters(mCipherSuite, (byte)mCompressionAlgorithm, mMasterSecret, mPeerCertificate, mPskIdentity, mSrpIdentity, mEncodedServerExtensions, mExtendedMasterSecret);
|
||||
}
|
||||
|
||||
public Builder SetCipherSuite(int cipherSuite)
|
||||
{
|
||||
mCipherSuite = cipherSuite;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder SetCompressionAlgorithm(byte compressionAlgorithm)
|
||||
{
|
||||
mCompressionAlgorithm = compressionAlgorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder SetExtendedMasterSecret(bool extendedMasterSecret)
|
||||
{
|
||||
mExtendedMasterSecret = extendedMasterSecret;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder SetMasterSecret(byte[] masterSecret)
|
||||
{
|
||||
mMasterSecret = masterSecret;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder SetPeerCertificate(Certificate peerCertificate)
|
||||
{
|
||||
mPeerCertificate = peerCertificate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder SetPskIdentity(byte[] pskIdentity)
|
||||
{
|
||||
mPskIdentity = pskIdentity;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder SetSrpIdentity(byte[] srpIdentity)
|
||||
{
|
||||
mSrpIdentity = srpIdentity;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder SetServerExtensions(IDictionary serverExtensions)
|
||||
{
|
||||
if (serverExtensions == null)
|
||||
{
|
||||
mEncodedServerExtensions = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
TlsProtocol.WriteExtensions(memoryStream, serverExtensions);
|
||||
mEncodedServerExtensions = memoryStream.ToArray();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void Validate(bool condition, string parameter)
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
throw new InvalidOperationException("Required session parameter '" + parameter + "' not configured");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int mCipherSuite;
|
||||
|
||||
private byte mCompressionAlgorithm;
|
||||
|
||||
private byte[] mMasterSecret;
|
||||
|
||||
private Certificate mPeerCertificate;
|
||||
|
||||
private byte[] mPskIdentity;
|
||||
|
||||
private byte[] mSrpIdentity;
|
||||
|
||||
private byte[] mEncodedServerExtensions;
|
||||
|
||||
private bool mExtendedMasterSecret;
|
||||
|
||||
public int CipherSuite => mCipherSuite;
|
||||
|
||||
public byte CompressionAlgorithm => mCompressionAlgorithm;
|
||||
|
||||
public bool IsExtendedMasterSecret => mExtendedMasterSecret;
|
||||
|
||||
public byte[] MasterSecret => mMasterSecret;
|
||||
|
||||
public Certificate PeerCertificate => mPeerCertificate;
|
||||
|
||||
public byte[] PskIdentity => mPskIdentity;
|
||||
|
||||
public byte[] SrpIdentity => mSrpIdentity;
|
||||
|
||||
private SessionParameters(int cipherSuite, byte compressionAlgorithm, byte[] masterSecret, Certificate peerCertificate, byte[] pskIdentity, byte[] srpIdentity, byte[] encodedServerExtensions, bool extendedMasterSecret)
|
||||
{
|
||||
mCipherSuite = cipherSuite;
|
||||
mCompressionAlgorithm = compressionAlgorithm;
|
||||
mMasterSecret = Arrays.Clone(masterSecret);
|
||||
mPeerCertificate = peerCertificate;
|
||||
mPskIdentity = Arrays.Clone(pskIdentity);
|
||||
mSrpIdentity = Arrays.Clone(srpIdentity);
|
||||
mEncodedServerExtensions = encodedServerExtensions;
|
||||
mExtendedMasterSecret = extendedMasterSecret;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (mMasterSecret != null)
|
||||
{
|
||||
Arrays.Fill(mMasterSecret, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public SessionParameters Copy()
|
||||
{
|
||||
return new SessionParameters(mCipherSuite, mCompressionAlgorithm, mMasterSecret, mPeerCertificate, mPskIdentity, mSrpIdentity, mEncodedServerExtensions, mExtendedMasterSecret);
|
||||
}
|
||||
|
||||
public IDictionary ReadServerExtensions()
|
||||
{
|
||||
if (mEncodedServerExtensions == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
MemoryStream input = new MemoryStream(mEncodedServerExtensions, writable: false);
|
||||
return TlsProtocol.ReadExtensions(input);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class SignatureAlgorithm
|
||||
{
|
||||
public const byte anonymous = 0;
|
||||
|
||||
public const byte rsa = 1;
|
||||
|
||||
public const byte dsa = 2;
|
||||
|
||||
public const byte ecdsa = 3;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class SignatureAndHashAlgorithm
|
||||
{
|
||||
protected readonly byte mHash;
|
||||
|
||||
protected readonly byte mSignature;
|
||||
|
||||
public virtual byte Hash => mHash;
|
||||
|
||||
public virtual byte Signature => mSignature;
|
||||
|
||||
public SignatureAndHashAlgorithm(byte hash, byte signature)
|
||||
{
|
||||
if (!TlsUtilities.IsValidUint8(hash))
|
||||
{
|
||||
throw new ArgumentException("should be a uint8", "hash");
|
||||
}
|
||||
if (!TlsUtilities.IsValidUint8(signature))
|
||||
{
|
||||
throw new ArgumentException("should be a uint8", "signature");
|
||||
}
|
||||
if (signature == 0)
|
||||
{
|
||||
throw new ArgumentException("MUST NOT be \"anonymous\"", "signature");
|
||||
}
|
||||
mHash = hash;
|
||||
mSignature = signature;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is SignatureAndHashAlgorithm))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
SignatureAndHashAlgorithm signatureAndHashAlgorithm = (SignatureAndHashAlgorithm)obj;
|
||||
if (signatureAndHashAlgorithm.Hash == Hash)
|
||||
{
|
||||
return signatureAndHashAlgorithm.Signature == Signature;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (Hash << 16) | Signature;
|
||||
}
|
||||
|
||||
public virtual void Encode(Stream output)
|
||||
{
|
||||
TlsUtilities.WriteUint8(Hash, output);
|
||||
TlsUtilities.WriteUint8(Signature, output);
|
||||
}
|
||||
|
||||
public static SignatureAndHashAlgorithm Parse(Stream input)
|
||||
{
|
||||
byte hash = TlsUtilities.ReadUint8(input);
|
||||
byte signature = TlsUtilities.ReadUint8(input);
|
||||
return new SignatureAndHashAlgorithm(hash, signature);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
internal class SignerInputBuffer : MemoryStream
|
||||
{
|
||||
private class SigStream : BaseOutputStream
|
||||
{
|
||||
private readonly ISigner s;
|
||||
|
||||
internal SigStream(ISigner s)
|
||||
{
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
public override void WriteByte(byte b)
|
||||
{
|
||||
s.Update(b);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buf, int off, int len)
|
||||
{
|
||||
s.BlockUpdate(buf, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateSigner(ISigner s)
|
||||
{
|
||||
Streams.WriteBufTo(this, new SigStream(s));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using Org.BouncyCastle.Crypto.Agreement.Srp;
|
||||
using Org.BouncyCastle.Crypto.Macs;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class SimulatedTlsSrpIdentityManager : TlsSrpIdentityManager
|
||||
{
|
||||
private static readonly byte[] PREFIX_PASSWORD = Strings.ToByteArray("password");
|
||||
|
||||
private static readonly byte[] PREFIX_SALT = Strings.ToByteArray("salt");
|
||||
|
||||
protected readonly Srp6GroupParameters mGroup;
|
||||
|
||||
protected readonly Srp6VerifierGenerator mVerifierGenerator;
|
||||
|
||||
protected readonly IMac mMac;
|
||||
|
||||
public static SimulatedTlsSrpIdentityManager GetRfc5054Default(Srp6GroupParameters group, byte[] seedKey)
|
||||
{
|
||||
Srp6VerifierGenerator srp6VerifierGenerator = new Srp6VerifierGenerator();
|
||||
srp6VerifierGenerator.Init(group, TlsUtilities.CreateHash(2));
|
||||
HMac hMac = new HMac(TlsUtilities.CreateHash(2));
|
||||
hMac.Init(new KeyParameter(seedKey));
|
||||
return new SimulatedTlsSrpIdentityManager(group, srp6VerifierGenerator, hMac);
|
||||
}
|
||||
|
||||
public SimulatedTlsSrpIdentityManager(Srp6GroupParameters group, Srp6VerifierGenerator verifierGenerator, IMac mac)
|
||||
{
|
||||
mGroup = group;
|
||||
mVerifierGenerator = verifierGenerator;
|
||||
mMac = mac;
|
||||
}
|
||||
|
||||
public virtual TlsSrpLoginParameters GetLoginParameters(byte[] identity)
|
||||
{
|
||||
mMac.BlockUpdate(PREFIX_SALT, 0, PREFIX_SALT.Length);
|
||||
mMac.BlockUpdate(identity, 0, identity.Length);
|
||||
byte[] array = new byte[mMac.GetMacSize()];
|
||||
mMac.DoFinal(array, 0);
|
||||
mMac.BlockUpdate(PREFIX_PASSWORD, 0, PREFIX_PASSWORD.Length);
|
||||
mMac.BlockUpdate(identity, 0, identity.Length);
|
||||
byte[] array2 = new byte[mMac.GetMacSize()];
|
||||
mMac.DoFinal(array2, 0);
|
||||
BigInteger verifier = mVerifierGenerator.GenerateVerifier(array, identity, array2);
|
||||
return new TlsSrpLoginParameters(mGroup, verifier, array);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using System.Collections;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class SrpTlsClient : AbstractTlsClient
|
||||
{
|
||||
protected TlsSrpGroupVerifier mGroupVerifier;
|
||||
|
||||
protected byte[] mIdentity;
|
||||
|
||||
protected byte[] mPassword;
|
||||
|
||||
protected virtual bool RequireSrpServerExtension => false;
|
||||
|
||||
public SrpTlsClient(byte[] identity, byte[] password)
|
||||
: this(new DefaultTlsCipherFactory(), new DefaultTlsSrpGroupVerifier(), identity, password)
|
||||
{
|
||||
}
|
||||
|
||||
public SrpTlsClient(TlsCipherFactory cipherFactory, byte[] identity, byte[] password)
|
||||
: this(cipherFactory, new DefaultTlsSrpGroupVerifier(), identity, password)
|
||||
{
|
||||
}
|
||||
|
||||
public SrpTlsClient(TlsCipherFactory cipherFactory, TlsSrpGroupVerifier groupVerifier, byte[] identity, byte[] password)
|
||||
: base(cipherFactory)
|
||||
{
|
||||
mGroupVerifier = groupVerifier;
|
||||
mIdentity = Arrays.Clone(identity);
|
||||
mPassword = Arrays.Clone(password);
|
||||
}
|
||||
|
||||
public override int[] GetCipherSuites()
|
||||
{
|
||||
return new int[1] { 49182 };
|
||||
}
|
||||
|
||||
public override IDictionary GetClientExtensions()
|
||||
{
|
||||
IDictionary dictionary = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions());
|
||||
TlsSrpUtilities.AddSrpExtension(dictionary, mIdentity);
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
public override void ProcessServerExtensions(IDictionary serverExtensions)
|
||||
{
|
||||
if (!TlsUtilities.HasExpectedEmptyExtensionData(serverExtensions, 12, 47) && RequireSrpServerExtension)
|
||||
{
|
||||
throw new TlsFatalAlert(47);
|
||||
}
|
||||
base.ProcessServerExtensions(serverExtensions);
|
||||
}
|
||||
|
||||
public override TlsKeyExchange GetKeyExchange()
|
||||
{
|
||||
int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
|
||||
switch (keyExchangeAlgorithm)
|
||||
{
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
return CreateSrpKeyExchange(keyExchangeAlgorithm);
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
}
|
||||
|
||||
public override TlsAuthentication GetAuthentication()
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mGroupVerifier, mIdentity, mPassword);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class SrpTlsServer : AbstractTlsServer
|
||||
{
|
||||
protected TlsSrpIdentityManager mSrpIdentityManager;
|
||||
|
||||
protected byte[] mSrpIdentity = null;
|
||||
|
||||
protected TlsSrpLoginParameters mLoginParameters = null;
|
||||
|
||||
public SrpTlsServer(TlsSrpIdentityManager srpIdentityManager)
|
||||
: this(new DefaultTlsCipherFactory(), srpIdentityManager)
|
||||
{
|
||||
}
|
||||
|
||||
public SrpTlsServer(TlsCipherFactory cipherFactory, TlsSrpIdentityManager srpIdentityManager)
|
||||
: base(cipherFactory)
|
||||
{
|
||||
mSrpIdentityManager = srpIdentityManager;
|
||||
}
|
||||
|
||||
protected virtual TlsSignerCredentials GetDsaSignerCredentials()
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
protected virtual TlsSignerCredentials GetRsaSignerCredentials()
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
|
||||
protected override int[] GetCipherSuites()
|
||||
{
|
||||
return new int[6] { 49186, 49183, 49185, 49182, 49184, 49181 };
|
||||
}
|
||||
|
||||
public override void ProcessClientExtensions(IDictionary clientExtensions)
|
||||
{
|
||||
base.ProcessClientExtensions(clientExtensions);
|
||||
mSrpIdentity = TlsSrpUtilities.GetSrpExtension(clientExtensions);
|
||||
}
|
||||
|
||||
public override int GetSelectedCipherSuite()
|
||||
{
|
||||
int selectedCipherSuite = base.GetSelectedCipherSuite();
|
||||
if (TlsSrpUtilities.IsSrpCipherSuite(selectedCipherSuite))
|
||||
{
|
||||
if (mSrpIdentity != null)
|
||||
{
|
||||
mLoginParameters = mSrpIdentityManager.GetLoginParameters(mSrpIdentity);
|
||||
}
|
||||
if (mLoginParameters == null)
|
||||
{
|
||||
throw new TlsFatalAlert(115);
|
||||
}
|
||||
}
|
||||
return selectedCipherSuite;
|
||||
}
|
||||
|
||||
public override TlsCredentials GetCredentials()
|
||||
{
|
||||
return TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite) switch
|
||||
{
|
||||
21 => null,
|
||||
22 => GetDsaSignerCredentials(),
|
||||
23 => GetRsaSignerCredentials(),
|
||||
_ => throw new TlsFatalAlert(80),
|
||||
};
|
||||
}
|
||||
|
||||
public override TlsKeyExchange GetKeyExchange()
|
||||
{
|
||||
int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite);
|
||||
switch (keyExchangeAlgorithm)
|
||||
{
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
return CreateSrpKeyExchange(keyExchangeAlgorithm);
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange)
|
||||
{
|
||||
return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mSrpIdentity, mLoginParameters);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class SrtpProtectionProfile
|
||||
{
|
||||
public const int SRTP_AES128_CM_HMAC_SHA1_80 = 1;
|
||||
|
||||
public const int SRTP_AES128_CM_HMAC_SHA1_32 = 2;
|
||||
|
||||
public const int SRTP_NULL_HMAC_SHA1_80 = 5;
|
||||
|
||||
public const int SRTP_NULL_HMAC_SHA1_32 = 6;
|
||||
|
||||
public const int SRTP_AEAD_AES_128_GCM = 7;
|
||||
|
||||
public const int SRTP_AEAD_AES_256_GCM = 8;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class Ssl3Mac : IMac
|
||||
{
|
||||
private const byte IPAD_BYTE = 54;
|
||||
|
||||
private const byte OPAD_BYTE = 92;
|
||||
|
||||
internal static readonly byte[] IPAD = GenPad(54, 48);
|
||||
|
||||
internal static readonly byte[] OPAD = GenPad(92, 48);
|
||||
|
||||
private readonly IDigest digest;
|
||||
|
||||
private readonly int padLength;
|
||||
|
||||
private byte[] secret;
|
||||
|
||||
public virtual string AlgorithmName => digest.AlgorithmName + "/SSL3MAC";
|
||||
|
||||
public Ssl3Mac(IDigest digest)
|
||||
{
|
||||
this.digest = digest;
|
||||
if (digest.GetDigestSize() == 20)
|
||||
{
|
||||
padLength = 40;
|
||||
}
|
||||
else
|
||||
{
|
||||
padLength = 48;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Init(ICipherParameters parameters)
|
||||
{
|
||||
secret = Arrays.Clone(((KeyParameter)parameters).GetKey());
|
||||
Reset();
|
||||
}
|
||||
|
||||
public virtual int GetMacSize()
|
||||
{
|
||||
return digest.GetDigestSize();
|
||||
}
|
||||
|
||||
public virtual void Update(byte input)
|
||||
{
|
||||
digest.Update(input);
|
||||
}
|
||||
|
||||
public virtual void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
digest.BlockUpdate(input, inOff, len);
|
||||
}
|
||||
|
||||
public virtual int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
byte[] array = new byte[digest.GetDigestSize()];
|
||||
digest.DoFinal(array, 0);
|
||||
digest.BlockUpdate(secret, 0, secret.Length);
|
||||
digest.BlockUpdate(OPAD, 0, padLength);
|
||||
digest.BlockUpdate(array, 0, array.Length);
|
||||
int result = digest.DoFinal(output, outOff);
|
||||
Reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
digest.Reset();
|
||||
digest.BlockUpdate(secret, 0, secret.Length);
|
||||
digest.BlockUpdate(IPAD, 0, padLength);
|
||||
}
|
||||
|
||||
private static byte[] GenPad(byte b, int count)
|
||||
{
|
||||
byte[] array = new byte[count];
|
||||
Arrays.Fill(array, b);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class SupplementalDataEntry
|
||||
{
|
||||
protected readonly int mDataType;
|
||||
|
||||
protected readonly byte[] mData;
|
||||
|
||||
public virtual int DataType => mDataType;
|
||||
|
||||
public virtual byte[] Data => mData;
|
||||
|
||||
public SupplementalDataEntry(int dataType, byte[] data)
|
||||
{
|
||||
mDataType = dataType;
|
||||
mData = data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public abstract class SupplementalDataType
|
||||
{
|
||||
public const int user_mapping_data = 0;
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Modes;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class TlsAeadCipher : TlsCipher
|
||||
{
|
||||
public const int NONCE_RFC5288 = 1;
|
||||
|
||||
internal const int NONCE_DRAFT_CHACHA20_POLY1305 = 2;
|
||||
|
||||
protected readonly TlsContext context;
|
||||
|
||||
protected readonly int macSize;
|
||||
|
||||
protected readonly int record_iv_length;
|
||||
|
||||
protected readonly IAeadBlockCipher encryptCipher;
|
||||
|
||||
protected readonly IAeadBlockCipher decryptCipher;
|
||||
|
||||
protected readonly byte[] encryptImplicitNonce;
|
||||
|
||||
protected readonly byte[] decryptImplicitNonce;
|
||||
|
||||
protected readonly int nonceMode;
|
||||
|
||||
public TlsAeadCipher(TlsContext context, IAeadBlockCipher clientWriteCipher, IAeadBlockCipher serverWriteCipher, int cipherKeySize, int macSize)
|
||||
: this(context, clientWriteCipher, serverWriteCipher, cipherKeySize, macSize, 1)
|
||||
{
|
||||
}
|
||||
|
||||
internal TlsAeadCipher(TlsContext context, IAeadBlockCipher clientWriteCipher, IAeadBlockCipher serverWriteCipher, int cipherKeySize, int macSize, int nonceMode)
|
||||
{
|
||||
if (!TlsUtilities.IsTlsV12(context))
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
this.nonceMode = nonceMode;
|
||||
int num;
|
||||
switch (nonceMode)
|
||||
{
|
||||
case 1:
|
||||
num = 4;
|
||||
record_iv_length = 8;
|
||||
break;
|
||||
case 2:
|
||||
num = 12;
|
||||
record_iv_length = 0;
|
||||
break;
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
this.context = context;
|
||||
this.macSize = macSize;
|
||||
int num2 = 2 * cipherKeySize + 2 * num;
|
||||
byte[] array = TlsUtilities.CalculateKeyBlock(context, num2);
|
||||
int num3 = 0;
|
||||
KeyParameter keyParameter = new KeyParameter(array, num3, cipherKeySize);
|
||||
num3 += cipherKeySize;
|
||||
KeyParameter keyParameter2 = new KeyParameter(array, num3, cipherKeySize);
|
||||
num3 += cipherKeySize;
|
||||
byte[] array2 = Arrays.CopyOfRange(array, num3, num3 + num);
|
||||
num3 += num;
|
||||
byte[] array3 = Arrays.CopyOfRange(array, num3, num3 + num);
|
||||
num3 += num;
|
||||
if (num3 != num2)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
KeyParameter key;
|
||||
KeyParameter key2;
|
||||
if (context.IsServer)
|
||||
{
|
||||
encryptCipher = serverWriteCipher;
|
||||
decryptCipher = clientWriteCipher;
|
||||
encryptImplicitNonce = array3;
|
||||
decryptImplicitNonce = array2;
|
||||
key = keyParameter2;
|
||||
key2 = keyParameter;
|
||||
}
|
||||
else
|
||||
{
|
||||
encryptCipher = clientWriteCipher;
|
||||
decryptCipher = serverWriteCipher;
|
||||
encryptImplicitNonce = array2;
|
||||
decryptImplicitNonce = array3;
|
||||
key = keyParameter;
|
||||
key2 = keyParameter2;
|
||||
}
|
||||
byte[] nonce = new byte[num + record_iv_length];
|
||||
encryptCipher.Init(forEncryption: true, new AeadParameters(key, 8 * macSize, nonce));
|
||||
decryptCipher.Init(forEncryption: false, new AeadParameters(key2, 8 * macSize, nonce));
|
||||
}
|
||||
|
||||
public virtual int GetPlaintextLimit(int ciphertextLimit)
|
||||
{
|
||||
return ciphertextLimit - macSize - record_iv_length;
|
||||
}
|
||||
|
||||
public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
|
||||
{
|
||||
byte[] array = new byte[encryptImplicitNonce.Length + record_iv_length];
|
||||
switch (nonceMode)
|
||||
{
|
||||
case 1:
|
||||
Array.Copy(encryptImplicitNonce, 0, array, 0, encryptImplicitNonce.Length);
|
||||
TlsUtilities.WriteUint64(seqNo, array, encryptImplicitNonce.Length);
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
TlsUtilities.WriteUint64(seqNo, array, array.Length - 8);
|
||||
for (int i = 0; i < encryptImplicitNonce.Length; i++)
|
||||
{
|
||||
byte[] array3;
|
||||
byte[] array2 = (array3 = array);
|
||||
int num = i;
|
||||
nint num2 = num;
|
||||
array2[num] = (byte)(array3[num2] ^ encryptImplicitNonce[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
int outputSize = encryptCipher.GetOutputSize(len);
|
||||
byte[] array4 = new byte[record_iv_length + outputSize];
|
||||
if (record_iv_length != 0)
|
||||
{
|
||||
Array.Copy(array, array.Length - record_iv_length, array4, 0, record_iv_length);
|
||||
}
|
||||
int num3 = record_iv_length;
|
||||
byte[] additionalData = GetAdditionalData(seqNo, type, len);
|
||||
AeadParameters parameters = new AeadParameters(null, 8 * macSize, array, additionalData);
|
||||
try
|
||||
{
|
||||
encryptCipher.Init(forEncryption: true, parameters);
|
||||
num3 += encryptCipher.ProcessBytes(plaintext, offset, len, array4, num3);
|
||||
num3 += encryptCipher.DoFinal(array4, num3);
|
||||
}
|
||||
catch (Exception alertCause)
|
||||
{
|
||||
throw new TlsFatalAlert(80, alertCause);
|
||||
}
|
||||
if (num3 != array4.Length)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
return array4;
|
||||
}
|
||||
|
||||
public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
|
||||
{
|
||||
if (GetPlaintextLimit(len) < 0)
|
||||
{
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
byte[] array = new byte[decryptImplicitNonce.Length + record_iv_length];
|
||||
switch (nonceMode)
|
||||
{
|
||||
case 1:
|
||||
Array.Copy(decryptImplicitNonce, 0, array, 0, decryptImplicitNonce.Length);
|
||||
Array.Copy(ciphertext, offset, array, array.Length - record_iv_length, record_iv_length);
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
TlsUtilities.WriteUint64(seqNo, array, array.Length - 8);
|
||||
for (int i = 0; i < decryptImplicitNonce.Length; i++)
|
||||
{
|
||||
byte[] array3;
|
||||
byte[] array2 = (array3 = array);
|
||||
int num = i;
|
||||
nint num2 = num;
|
||||
array2[num] = (byte)(array3[num2] ^ decryptImplicitNonce[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
int inOff = offset + record_iv_length;
|
||||
int len2 = len - record_iv_length;
|
||||
int outputSize = decryptCipher.GetOutputSize(len2);
|
||||
byte[] array4 = new byte[outputSize];
|
||||
int num3 = 0;
|
||||
byte[] additionalData = GetAdditionalData(seqNo, type, outputSize);
|
||||
AeadParameters parameters = new AeadParameters(null, 8 * macSize, array, additionalData);
|
||||
try
|
||||
{
|
||||
decryptCipher.Init(forEncryption: false, parameters);
|
||||
num3 += decryptCipher.ProcessBytes(ciphertext, inOff, len2, array4, num3);
|
||||
num3 += decryptCipher.DoFinal(array4, num3);
|
||||
}
|
||||
catch (Exception alertCause)
|
||||
{
|
||||
throw new TlsFatalAlert(20, alertCause);
|
||||
}
|
||||
if (num3 != array4.Length)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
return array4;
|
||||
}
|
||||
|
||||
protected virtual byte[] GetAdditionalData(long seqNo, byte type, int len)
|
||||
{
|
||||
byte[] array = new byte[13];
|
||||
TlsUtilities.WriteUint64(seqNo, array, 0);
|
||||
TlsUtilities.WriteUint8(type, array, 8);
|
||||
TlsUtilities.WriteVersion(context.ServerVersion, array, 9);
|
||||
TlsUtilities.WriteUint16(len, array, 11);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public interface TlsAgreementCredentials : TlsCredentials
|
||||
{
|
||||
byte[] GenerateAgreement(AsymmetricKeyParameter peerPublicKey);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user