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