public void RegisterSessionTicket(ReadableBuffer buffer) { //slice off the head first buffer = buffer.Slice(HandshakeProcessor.HandshakeHeaderSize); uint ticketAge, ageRandom; buffer = buffer.SliceBigEndian(out ticketAge); buffer = buffer.SliceBigEndian(out ageRandom); var ticketData = BufferExtensions.SliceVector <ushort>(ref buffer); if (buffer.Length > 0) { //Extensions buffer = BufferExtensions.SliceVector <ushort>(ref buffer); if (buffer.Length > 0) { //seems we can resume data ExtensionType type; buffer = buffer.SliceBigEndian(out type); if (type != ExtensionType.ticket_early_data_info) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Early session ticket received had an invalid extension"); } } } }
public static void ReadServerHello(ReadableBuffer readable, IConnectionStateTls13 connectionState) { var original = readable; ushort version, cipherCode; readable = readable.Slice(HandshakeProcessor.HandshakeHeaderSize); readable = readable.SliceBigEndian(out version); //skip random readable = readable.Slice(RandomLength); readable = readable.SliceBigEndian(out cipherCode); connectionState.CipherSuite = connectionState.CryptoProvider.GetCipherSuiteFromCode(cipherCode, connectionState.Version); if (connectionState.CipherSuite == null) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Could not get a cipher suite during server hello"); } connectionState.StartHandshakeHash(original); readable = BufferExtensions.SliceVector <ushort>(ref readable); ExtensionType ext; readable = readable.SliceBigEndian(out ext); if (ext != ExtensionType.key_share) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "There was no keyshare on the server hello"); } readable = BufferExtensions.SliceVector <ushort>(ref readable); NamedGroup group; readable = readable.SliceBigEndian(out group); if (group != connectionState.KeyShare.NamedGroup) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "The named group didn't match the keyshare during server hello"); } readable = BufferExtensions.SliceVector <ushort>(ref readable); connectionState.KeyShare.SetPeerKey(readable); }
public unsafe static WritableBuffer SendKeyExchange(WritableBuffer buffer, IConnectionStateTls12 connectionState) { var messageLength = 4 + connectionState.KeyShare.KeyExchangeSize; buffer.Ensure(messageLength); var bookMark = buffer.Memory; buffer.WriteBigEndian(ECCurveType.named_curve); buffer.WriteBigEndian(connectionState.KeyShare.NamedGroup); buffer.WriteBigEndian((byte)connectionState.KeyShare.KeyExchangeSize); connectionState.KeyShare.WritePublicKey(ref buffer); buffer.WriteBigEndian(connectionState.SignatureScheme); BufferExtensions.WriteVector <ushort>(ref buffer, (writer, state) => { var tempBuffer = stackalloc byte[connectionState.ClientRandom.Length * 2 + messageLength]; var tmpSpan = new Span <byte>(tempBuffer, connectionState.ClientRandom.Length * 2 + messageLength); connectionState.ClientRandom.CopyTo(tmpSpan); tmpSpan = tmpSpan.Slice(connectionState.ClientRandom.Length); connectionState.ServerRandom.CopyTo(tmpSpan); tmpSpan = tmpSpan.Slice(connectionState.ServerRandom.Length); bookMark.Span.Slice(0, messageLength).CopyTo(tmpSpan); connectionState.Certificate.SignHash(connectionState.CryptoProvider.HashProvider, connectionState.SignatureScheme, ref writer, tempBuffer, connectionState.ClientRandom.Length * 2 + messageLength); return(writer); }, connectionState); return(buffer); }
public static void ReadApplicationProtocolExtension(ReadableBuffer buffer, IConnectionState connectionState) { buffer = BufferExtensions.SliceVector <ushort>(ref buffer); //if(connectionState.Listener.ServerNameProvider.MatchServerName(buffer)) //buffer.Equals() }
public static WritableBuffer CreateNewSessionKey(WritableBuffer buffer, IConnectionStateTls13 state) { var lifetime = TicketLifeTimeInHours * 60 * 60; buffer.WriteBigEndian((uint)lifetime); buffer.Ensure(4); state.CryptoProvider.FillWithRandom(buffer.Memory.Slice(0, 4)); buffer.Advance(4); BufferExtensions.WriteVector <ushort>(ref buffer, (writer, conn) => { state.ResumptionProvider.GenerateSessionTicket(ref writer, conn); return(writer); }, state); BufferExtensions.WriteVector <ushort>(ref buffer, (writer, conn) => { writer.WriteBigEndian(ExtensionType.ticket_early_data_info); writer.WriteBigEndian <ushort>(sizeof(uint)); uint maxData = 1024 * 2; writer.WriteBigEndian(maxData); return(writer); }, state); return(buffer); }
public static void ReadCertificates(ReadableBuffer buffer, SecurePipelineListener listener) { buffer = buffer.Slice(HandshakeProcessor.HandshakeHeaderSize); //ignore context BufferExtensions.SliceVector <byte>(ref buffer); //slice the list buffer = BufferExtensions.SliceVector24Bit(ref buffer); X509Certificate2Collection collection; if (listener.CertificateValidation == null) { collection = null; } else { collection = new X509Certificate2Collection(); } while (buffer.Length > 0) { var cert = BufferExtensions.SliceVector24Bit(ref buffer); var ext = BufferExtensions.SliceVector <ushort>(ref buffer); if (cert.Length > 0 && collection != null) { var x509 = new X509Certificate2(cert.ToArray()); collection.Add(x509); } } if (collection != null) { if (!listener.CertificateValidation(collection)) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.bad_certificate, "Failed to verify the certificate chain via the callback"); } } }
public static void SendFlightOne(ref WritableBuffer writer, IConnectionStateTls13 connectionState) { connectionState.WriteHandshake(ref writer, HandshakeType.encrypted_extensions, (buffer, state) => { BufferExtensions.WriteVector <ushort>(ref buffer, ExtensionsWrite.WriteExtensionList, state); return(buffer); }); }
public static void WriteSignatureSchemes(ref WritableBuffer buffer, IConnectionStateTls13 connectionState) { buffer.WriteBigEndian(ExtensionType.signature_algorithms); BufferExtensions.WriteVector <ushort>(ref buffer, (writer, state) => { connectionState.CryptoProvider.WriteSignatureSchemes(ref writer); return(writer); }, connectionState); }
public static void WriteSupportedGroups(ref WritableBuffer buffer, IConnectionStateTls13 connectionState) { buffer.WriteBigEndian(ExtensionType.supported_groups); BufferExtensions.WriteVector <ushort>(ref buffer, (writer, state) => { connectionState.CryptoProvider.WriteSupportedGroups(ref writer); return(writer); }, connectionState); }
public static void WriteServerKeyshare(ref WritableBuffer buffer, IConnectionState connectionState) { buffer.WriteBigEndian(ExtensionType.key_share); BufferExtensions.WriteVector <ushort>(ref buffer, (writer, state) => { WriteKeyShare(ref writer, state.KeyShare); return(writer); }, connectionState); }
public static void ReadSupportedGroups(ReadableBuffer buffer, IConnectionStateTls13 connectionState) { if (connectionState.KeyShare != null) { return; } buffer = BufferExtensions.SliceVector <ushort>(ref buffer); connectionState.KeyShare = connectionState.CryptoProvider.GetKeyshareFromNamedGroups(buffer); }
public static WritableBuffer SendHelloRetry(WritableBuffer buffer, IConnectionStateTls13 connectionState) { if (connectionState.State == StateType.WaitHelloRetry) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "need to send a hello retry but have already sent one"); } buffer.WriteBigEndian(connectionState.Version); BufferExtensions.WriteVector <ushort>(ref buffer, ExtensionsWrite.WriteExtensionList, connectionState); return(buffer); }
public static void ReadKeyshare(ReadableBuffer buffer, IConnectionStateTls13 connectionState) { if (connectionState.KeyShare?.HasPeerKey == true) { return; } buffer = BufferExtensions.SliceVector <ushort>(ref buffer); var ks = connectionState.CryptoProvider.GetKeyshareFromKeyshare(buffer); connectionState.KeyShare = ks ?? connectionState.KeyShare; }
public static WritableBuffer SendServerHello13(WritableBuffer buffer, IConnectionStateTls13 connectionState) { buffer.Ensure(RandomLength + sizeof(ushort)); buffer.WriteBigEndian(connectionState.Version); var memoryToFill = buffer.Memory.Slice(0, RandomLength); connectionState.CryptoProvider.FillWithRandom(memoryToFill); buffer.Advance(RandomLength); buffer.WriteBigEndian(connectionState.CipherSuite.CipherCode); BufferExtensions.WriteVector <ushort>(ref buffer, ExtensionsWrite.WriteExtensionList, connectionState); return(buffer); }
public static void WriteHandshake(this IConnectionStateTls13 state, ref WritableBuffer writer, HandshakeType handshakeType, Func <WritableBuffer, IConnectionStateTls13, WritableBuffer> contentWriter) { var dataWritten = writer.BytesWritten; writer.WriteBigEndian(handshakeType); BufferExtensions.WriteVector24Bit(ref writer, contentWriter, state); if (state.HandshakeHash != null) { var hashBuffer = writer.AsReadableBuffer().Slice(dataWritten); state.HandshakeHash.HashData(hashBuffer); } }
public static void WriteHandshake <T>(this T state, ref WritableBuffer writer, HandshakeType handshakeType, Func <WritableBuffer, T, WritableBuffer> contentWriter) where T : IConnectionState { state.Logger?.LogTrace("Writing handshake {handshake type}", handshakeType); var dataWritten = writer.BytesWritten; writer.WriteBigEndian(handshakeType); BufferExtensions.WriteVector24Bit <T>(ref writer, contentWriter, state); if (state.HandshakeHash != null) { var hashBuffer = writer.AsReadableBuffer().Slice(dataWritten); state.HandshakeHash.HashData(hashBuffer); } }
public static void WriteClientKeyshares(ref WritableBuffer buffer, IConnectionStateTls13 connectionState) { buffer.WriteBigEndian(ExtensionType.key_share); BufferExtensions.WriteVector <ushort>(ref buffer, (innerWriter, innerState) => { BufferExtensions.WriteVector <ushort>(ref innerWriter, (writer, state) => { WriteKeyShare(ref writer, state.KeyShare); return(writer); }, innerState); return(innerWriter); }, connectionState); }
public void MatchServerName(ReadableBuffer buffer, IConnectionState state) { buffer = BufferExtensions.SliceVector <ushort>(ref buffer); while (buffer.Length > 0) { var nameType = buffer.ReadBigEndian <byte>(); buffer = buffer.Slice(sizeof(byte)); var nameBuffer = BufferExtensions.SliceVector <ushort>(ref buffer); if (nameType == 0) { state.ServerName = nameBuffer.GetUtf8String(); } } }
public static WritableBuffer WriteCertificate(WritableBuffer writer, IConnectionStateTls13 connectionState) { writer.WriteBigEndian <byte>(0); BufferExtensions.WriteVector24Bit(ref writer, (buffer, state) => { WriteCertificateEntry(ref buffer, state.Certificate.CertificateData); for (int i = 0; i < state.Certificate.CertificateChain.Length; i++) { WriteCertificateEntry(ref buffer, state.Certificate.CertificateChain[i]); } return(buffer); }, connectionState); return(writer); }
public static WritableBuffer SendCertificates(WritableBuffer buffer, IConnectionStateTls12 connectionState) { var startOfMessage = buffer.BytesWritten; BufferExtensions.WriteVector24Bit(ref buffer, (writer, state) => { WriteCertificateEntry(ref writer, connectionState.Certificate.CertificateData); foreach (var b in connectionState.Certificate.CertificateChain) { WriteCertificateEntry(ref writer, b); } return(buffer); }, connectionState); return(buffer); }
public static WritableBuffer WriteClientHello(WritableBuffer buffer, IConnectionStateTls13 connectionState) { buffer.WriteBigEndian <ushort>(0x0303); buffer.Ensure(RandomLength); connectionState.CryptoProvider.FillWithRandom(buffer.Memory.Slice(0, RandomLength)); buffer.Advance(RandomLength); //legacy sessionid buffer.WriteBigEndian((byte)0); connectionState.CryptoProvider.WriteCipherSuites(ref buffer); //legacy compression buffer.WriteBigEndian((byte)1); buffer.WriteBigEndian((byte)0); connectionState.KeyShare = connectionState.CryptoProvider.GetDefaultKeyShare(); BufferExtensions.WriteVector <ushort>(ref buffer, ExtensionsWrite.WriteExtensionList, connectionState); return(buffer); }
public static void ReadSignatureScheme(ReadableBuffer buffer, IConnectionState connectionState) { buffer = BufferExtensions.SliceVector <ushort>(ref buffer); while (buffer.Length > 1) { SignatureScheme scheme; buffer = buffer.SliceBigEndian(out scheme); var cert = connectionState.CertificateList.GetCertificate(connectionState.ServerName, scheme); if (cert != null) { connectionState.Certificate = cert; connectionState.SignatureScheme = scheme; return; } } Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Failed to find a signature scheme that matches"); }
public static void ReadPskKeyExchangeMode(ReadableBuffer buffer, IConnectionStateTls13 connectionState) { buffer = BufferExtensions.SliceVector <byte>(ref buffer); while (buffer.Length > 0) { PskKeyExchangeMode mode; buffer = buffer.SliceBigEndian(out mode); if (connectionState.PskKeyExchangeMode == PskKeyExchangeMode.none) { connectionState.PskKeyExchangeMode = mode; } else { connectionState.PskKeyExchangeMode |= mode; } } }
public static void ReadClientHello(ref ReadableBuffer readable, IConnectionState connectionState) { readable = readable.Slice(HandshakeProcessor.HandshakeHeaderSize); readable = readable.Slice(sizeof(ushort)); connectionState.SetClientRandom(readable.Slice(0, RandomLength)); readable = readable.Slice(RandomLength); //We don't support sessions via id so slice and throw BufferExtensions.SliceVector <byte>(ref readable); //Slice Cipher Suite var ciphers = BufferExtensions.SliceVector <ushort>(ref readable); if (connectionState.CipherSuite == null) { connectionState.CipherSuite = connectionState.CryptoProvider.GetCipherSuiteFromExtension(ciphers, connectionState.Version); } //Skip compression BufferExtensions.SliceVector <byte>(ref readable); }
public override byte[] Write() { var extras = CreateExtras(); var key = CreateKey(); var body = CreateBody(); var header = CreateHeader(extras, body, key); var buffer = new byte[BufferExtensions.GetLengthSafe(extras) + BufferExtensions.GetLengthSafe(body) + BufferExtensions.GetLengthSafe(key) + BufferExtensions.GetLengthSafe(header)]; System.Buffer.BlockCopy(header, 0, buffer, 0, header.Length); System.Buffer.BlockCopy(extras, 0, buffer, header.Length, extras.Length); System.Buffer.BlockCopy(key, 0, buffer, header.Length + extras.Length, key.Length); System.Buffer.BlockCopy(body, 0, buffer, header.Length + extras.Length + key.Length, body.Length); return(buffer); }
public static TlsVersion ReadSupportedVersion(ReadableBuffer buffer, TlsVersion[] supportedVersions) { TlsVersion returnVersion = 0; buffer = BufferExtensions.SliceVector <byte>(ref buffer); while (buffer.Length > 1) { TlsVersion version; buffer = buffer.SliceBigEndian(out version); if (supportedVersions.Contains(version)) { if (version > returnVersion) { returnVersion = version; } } } return(returnVersion); }
// Fix some incorrect ines header entries that QuickNES uses to load games. // we need to do this from the raw file since QuickNES hasn't had time to process it yet. private byte[] FixInesHeader(byte[] file) { string sha1 = BufferExtensions.HashSHA1(file); bool didSomething = false; Console.WriteLine(sha1); if (sha1 == "93010514AA1300499ABC8F145D6ABCDBF3084090") // Ms. Pac Man (Tengen) [!] { file[6] &= 0xFE; didSomething = true; } if (didSomething) { Console.WriteLine("iNES header error detected, adjusting settings..."); Console.WriteLine(sha1); } return(file); }
private static TlsVersion GetVersion(ref ReadableBuffer buffer) { //Jump the version header and the randoms buffer = buffer.Slice(HandshakeProcessor.HandshakeHeaderSize); TlsVersion version; buffer = buffer.SliceBigEndian(out version); if (!_supportedVersion.Contains(version)) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.protocol_version, $"The version was not in the supported list {version}"); } //Slice out the random buffer = buffer.Slice(Hello.RandomLength); //No sessions slice and dump BufferExtensions.SliceVector <byte>(ref buffer); //Skip the cipher suites if we find a version we are happy with //then the cipher suite is dealt with by that version BufferExtensions.SliceVector <ushort>(ref buffer); //Skip compression, we don't care about that either, we just want to get to the end BufferExtensions.SliceVector <byte>(ref buffer); //And here we are at the end, if we have no extensions then we must be the header version that //we accepted earlier if (buffer.Length == 0) { return(version); } buffer = BufferExtensions.SliceVector <ushort>(ref buffer); while (buffer.Length >= 8) { ExtensionType type; buffer = buffer.SliceBigEndian(out type); var ext = BufferExtensions.SliceVector <ushort>(ref buffer); if (type == ExtensionType.supported_versions) { //Scan the version for supported ones return(ExtensionsRead.ReadSupportedVersion(ext, _supportedVersion)); } } return(version); }
public static void ReadPskKey(ReadableBuffer pskBuffer, IConnectionStateTls13 connectionState) { var identities = BufferExtensions.SliceVector <ushort>(ref pskBuffer); while (identities.Length > 0) { var identity = BufferExtensions.SliceVector <ushort>(ref identities); long serviceId, keyId; identity = identity.SliceBigEndian(out serviceId); identity = identity.SliceBigEndian(out keyId); int ticketAge; identities = identities.SliceBigEndian(out ticketAge); if (!connectionState.ResumptionProvider.TryToResume(serviceId, keyId, identity, connectionState)) { continue; } if ((connectionState.PskKeyExchangeMode & PskKeyExchangeMode.psk_dhe_ke) == 0) { connectionState.KeyShare?.Dispose(); connectionState.KeyShare = null; } return; } }
private void Receive(IAsyncResult ar) { var receivedBytes = 0; try { receivedBytes = _socket.EndReceive(ar); } catch (Exception ex) { Disconnect($"Receive Exception: {ex}"); } // Check if the socket was closed. if (receivedBytes == 0) { Disconnect(); return; } // Check the message header. if (receivedBytes < InHeaderSize) { Disconnect("The received packets header size is incorrect."); return; } // TODO Properly Process incomming bytes. using (var stream = new MemoryStream(_receiveBuffer, 0, receivedBytes)) using (var reader = new BinaryReader(stream)) { var size = reader.ReadUInt16(); var encrypted = reader.ReadByte() == 1; var body = reader.ReadBytes(size - InHeaderSize); if (encrypted) { body = BDOCrypt.Xor(body, 0, body.Length); } using (var messageStream = new MemoryStream(body)) using (var message = new BinaryReader(messageStream)) { var messageId = message.ReadUInt16(); // MessageId Logging.Server($"Received(Size:{size}, Encrypted: {encrypted}, MessageId: {messageId}, 0x{messageId:X2})"); //Logging.Server(BufferExtensions.ToHex(body.Skip(2).ToArray())); var handler = MessageTable.FindMessageHandler(messageId); if (handler != null) { handler.Handle(this, message); } else { Logging.Server($"Unknown Message Received: Size:{size}, Encrypted: {encrypted}, MessageId: {messageId} (0x{messageId:X2})"); Logging.Server(BufferExtensions.ToHex(body.Skip(2).ToArray())); } } } // Start receiving more data. BeginReceive(); }