init commit

This commit is contained in:
2025-10-09 09:57:24 +09:00
commit 4d551bd74f
6636 changed files with 1218703 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
namespace Org.BouncyCastle.Crypto.Tls;
public abstract class AbstractTlsAgreementCredentials : AbstractTlsCredentials, TlsAgreementCredentials, TlsCredentials
{
public abstract byte[] GenerateAgreement(AsymmetricKeyParameter peerPublicKey);
}

View File

@@ -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);
}
}

View File

@@ -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)
{
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,6 @@
namespace Org.BouncyCastle.Crypto.Tls;
public abstract class AbstractTlsCredentials : TlsCredentials
{
public abstract Certificate Certificate { get; }
}

View File

@@ -0,0 +1,6 @@
namespace Org.BouncyCastle.Crypto.Tls;
public abstract class AbstractTlsEncryptionCredentials : AbstractTlsCredentials, TlsEncryptionCredentials, TlsCredentials
{
public abstract byte[] DecryptPreMasterSecret(byte[] encryptedPreMasterSecret);
}

View File

@@ -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();
}

View File

@@ -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()
{
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 + ")";
}
}

View File

@@ -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 + ")";
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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");
}
}

View File

@@ -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");
}
}

View File

@@ -0,0 +1,6 @@
namespace Org.BouncyCastle.Crypto.Tls;
public abstract class CertificateStatusType
{
public const byte ocsp = 1;
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,6 @@
namespace Org.BouncyCastle.Crypto.Tls;
public abstract class ChangeCipherSpec
{
public const byte change_cipher_spec = 1;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,8 @@
namespace Org.BouncyCastle.Crypto.Tls;
public abstract class CompressionMethod
{
public const byte cls_null = 0;
public const byte DEFLATE = 1;
}

View File

@@ -0,0 +1,8 @@
namespace Org.BouncyCastle.Crypto.Tls;
public abstract class ConnectionEnd
{
public const int server = 0;
public const int client = 1;
}

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -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),
};
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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++;
}
}

View File

@@ -0,0 +1,6 @@
namespace Org.BouncyCastle.Crypto.Tls;
internal interface DtlsHandshakeRetransmit
{
void ReceivedHandshakeRecord(int epoch, byte[] buf, int off, int len);
}

View File

@@ -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);
}
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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";
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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");
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,6 @@
namespace Org.BouncyCastle.Crypto.Tls;
public abstract class SupplementalDataType
{
public const int user_mapping_data = 0;
}

View File

@@ -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;
}
}

View File

@@ -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