Esempio n. 1
0
        private void SendClientHello()
        {
            var random = TLS12.GetRandom();

            _session.ClientRandom = random;
            var clientHello = new ClientHello
            {
                Random       = random,
                RSAPublicPem = _rsa.PublicPem
            };
            var request = new SecurityLayerMessage
            {
                Type = SecurityMessageType.ClientHello,
                Data = _serializer.Serialize <ClientHello>(clientHello)
            };
            var requestBytes = _serializer.Serialize <SecurityLayerMessage>(request);

            Send(requestBytes);

            var responseBytes = Receive();
            var message       = _serializer.Deserialize <SecurityLayerMessage>(responseBytes);
            var serverHello   = _serializer.Deserialize <ServerHello>(message.Data);

            _session.Id           = serverHello.SessionId;
            _session.ServerRandom = serverHello.Random;
            _session.RSAPublicPem = serverHello.RSAPublicPem;
        }
Esempio n. 2
0
 protected override void OnClientHello(byte[] buf, int size, IPEndPoint remoteEP)
 {
     if (ClientHello.TryUnpack(buf, 0, size, out _))
     {
         m_Socket.Send(m_ServerHello, 0, m_ServerHello.Length, remoteEP);
     }
 }
Esempio n. 3
0
 public override string ToString()
 {
     return(ClientHello.ToString() + Environment.NewLine +
            ServerHello.ToString() + Environment.NewLine +
            ClientKeyExchange.ToString() + Environment.NewLine +
            Finished.ToString());
 }
Esempio n. 4
0
 public static void HandleClientHello(LobbySession session, ClientHello hello)
 {
     session.CalculateNetworkKey(hello.Time, hello.Seed);
     session.SessionHash = XxHash.CalculateHash(Guid.NewGuid().ToByteArray());
     session.Send(new ServerHello
     {
         SessionHash = session.SessionHash
     });
 }
Esempio n. 5
0
        //Define the same method for the server side.
        public override Task <ServerHello> GetMessage(ClientHello request, ServerCallContext context)
        {
            string serverMessage = $@"Hello there {request.ClientName}";

            Console.WriteLine($@"Recevied message from client {request.ClientName}: {request.ClientMessage}");
            return(Task.FromResult(new ServerHello {
                ServerMessage = serverMessage, ServerName = _serverName, ServerNumber = _serverNumber
            }));
        }
Esempio n. 6
0
 public static bool TryUnpack(byte[] buf, int offset, int size, out ClientHello packet)
 {
     if (size <= 2)
     {
         packet = default;
         return(false);
     }
     packet = new ClientHello(buf[offset], buf[offset + 1]);
     return(true);
 }
Esempio n. 7
0
        public void TestJsonByteArrayIsBase64Encoded()
        {
            var rdm = new byte[] { 1, 2, 3 };
            var obj = new ClientHello {
                ephDHKey = rdm
            };

            var json = obj.ToJson();

            Assert.AreEqual("{\"ephDHKey\":\"" + rdm.ToBase64String() + "\"}", json);
        }
Esempio n. 8
0
        public static void ParseClientHelloRecord(BytesSegment bs, ref ClientHello ch, out int size)
        {
            var payloadLen = GetRecordPayloadLength(bs, ref ch.Version);

            size = 5 + payloadLen;
            if (bs.Len < size)
            {
                return;
            }
            bs.SubSelf(5);
            bs.Len = Math.Min(bs.Len, payloadLen);
            ParseClientHello(bs, ref ch);
        }
Esempio n. 9
0
        public async Task <ClientConnectionImpl> Run()
        {
            try
            {
                m_Socket = new UdpSocket();
                m_Socket.Bind(m_Settings.EndPoint.AddressFamily);
                if (!m_Settings.UseP2P)
                {
                    m_Socket.Connect(m_Settings.EndPoint);
                }
                byte[] cookie;
                if (m_Settings.Cookie == null)
                {
                    var buf = new ClientHello(Protocol.MajorVersion, Protocol.MinorVersion).Pack();
                    var req = new TimeoutRetryableRequester <ServerHello>(WaitServerHello(), () => Send(buf), m_Token);
                    var res = await req.Run();

                    cookie = res.Cookie;
                }
                else
                {
                    cookie = m_Settings.Cookie;
                }
                {
                    m_Token.ThrowIfCancellationRequested();

                    var    payload    = new HandshakeRequestPayload(Random.GenInt(), m_Randam);
                    byte[] payloadBuf = payload.Pack();
                    if (m_Settings.RSA != null)
                    {
                        payloadBuf = m_Settings.RSA.Encrypt(payloadBuf, RSAEncryptionPadding.Pkcs1);
                    }
                    var request = new HandshakeRequest(cookie, payloadBuf);

                    m_EncryptorKey = new EncryptorKey(request, payload, 0);

                    var res = await(new TimeoutRetryableRequester <HandshakeResult>(WaitHandshakeAccept(), () => Send(request.Pack()), m_Token)).Run();

                    m_Token.ThrowIfCancellationRequested();

                    return(new ClientConnectionImpl(res.ConnectionId, m_Socket, m_Settings, res.Encryptor, m_EncryptorGenerator));
                }
            }
            catch (Exception ex)
            {
                Log.Exception(ex);
                m_Socket.Dispose();
                m_EncryptorGenerator.Dispose();
                throw;
            }
        }
Esempio n. 10
0
        public bool ConnectToServer(IPEndPoint serverAddress, bool playerIsRed, string playerName)
        {
            var clientHello = new ClientHello(playerIsRed, playerName);

            server = new TcpClient();
            server.Connect(serverAddress);
            serverConnection = server.GetStream();
            Network.SendPacket(clientHello, serverConnection);
            var serverHello = (ServerHello)Network.ReceivePacket(serverConnection);

            this.playerName  = playerName;
            this.playerIsRed = serverHello.ColorIsRed;
            if (serverHello.EnemyName == null)
            {
                return(false);
            }
            enemyName = serverHello.EnemyName;
            return(true);
        }
Esempio n. 11
0
        private static async Task <Record> SendClientHelloAsync(TlsRequestParameters requestParameters)
        {
            if (requestParameters.CipherSuites == null)
            {
                requestParameters.CipherSuites = new CipherSuites[]
                {
                    Tls.CipherSuites.TLS_AES_128_GCM_SHA256,
                    Tls.CipherSuites.TLS_AES_256_GCM_SHA384,
                    Tls.CipherSuites.TLS_CHACHA20_POLY1305_SHA256,
                    Tls.CipherSuites.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                    Tls.CipherSuites.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                    Tls.CipherSuites.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
                    Tls.CipherSuites.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
                    Tls.CipherSuites.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
                    Tls.CipherSuites.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
                    Tls.CipherSuites.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
                    Tls.CipherSuites.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
                    Tls.CipherSuites.TLS_RSA_WITH_AES_128_GCM_SHA256,
                    Tls.CipherSuites.TLS_RSA_WITH_AES_256_GCM_SHA384,
                    Tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,
                    Tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA,
                    Tls.CipherSuites.TLS_RSA_WITH_3DES_EDE_CBC_SHA
                };
            }

            using (TcpClient client = new TcpClient())
            {
                await client.ConnectAsync(requestParameters.Host, requestParameters.Port);

                NetworkStream s = client.GetStream();
                s.ReadTimeout = ServerReadTimeoutInSeconds * 1000;

                ClientHello hello = new ClientHello(
                    requestParameters.HandshakeVersion,
                    requestParameters.CipherSuites,
                    requestParameters.RecordVersion);

                await WriteRecordToStreamAsync(hello, s);

                return(await HandleResponse(s, requestParameters));
            }
        }
    public byte[] ConstructClientHello(ClientMessageType type, ushort clientId, string playerName)
    {
        fbBuilder.Clear();

        StringOffset playerNameOffset = fbBuilder.CreateString(playerName);

        ClientHello.StartClientHello(fbBuilder);
        ClientHello.AddPlayerName(fbBuilder, playerNameOffset);
        Offset <ClientHello> clientHelloOffset = ClientHello.EndClientHello(fbBuilder);

        ClientMessage.StartClientMessage(fbBuilder);
        //var clientIdOffset = clientId;
        ClientMessage.AddClientId(fbBuilder, clientId);
        ClientMessage.AddMsgType(fbBuilder, type);
        ClientMessage.AddMsg(fbBuilder, clientHelloOffset.Value);
        Offset <ClientMessage> clientMessageOffset = ClientMessage.EndClientMessage(fbBuilder);

        ClientMessage.FinishClientMessageBuffer(fbBuilder, clientMessageOffset);

        return(fbBuilder.SizedByteArray());
    }
Esempio n. 13
0
        public async Task <ClientHello> ReadClientHello()
        {
            var recordHeader = new BytesSegment(new byte[5]);
            await RealBaseStream.ReadFullAsyncR(recordHeader);

            MyStreamWrapper.Queue = recordHeader;
            ushort ver = 0;
            int    recordPayloadLength = GetRecordPayloadLength(recordHeader, ref ver);

            var record = new BytesSegment(new byte[5 + recordPayloadLength]);

            recordHeader.CopyTo(record);
            var msg = record.Sub(5);
            await RealBaseStream.ReadFullAsyncR(msg);

            MyStreamWrapper.Queue = record;
            var ch = new ClientHello();

            ParseClientHello(msg, ref ch);
            return(ch);
        }
Esempio n. 14
0
        public bool GetServerHello(byte[] clientHello, out byte[] serverHello)
        {
            serverHello = null;

            if (!ClientHello.Parse(clientHello, out ClientHello ch))
            {
                return(false);
            }

            var nonce = ByteHelper.GetRandom(32);

            var proofOfWorkDetails = ByteHelper.GetRandom(32);

            proofOfWorkDetails[0] = 15;

            serverHello = ByteHelper.Combine(nonce, proofOfWorkDetails);

            Session.ClientEphDHPubKey = ch.ephDHKey;

            return(true);
        }
Esempio n. 15
0
            public static ByteSpan Test_CompressionLengthOverrunClientHello(ClientHello clientHello, ByteSpan writer)
            {
                ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)ProtocolVersion.DTLS1_2);
                writer = writer.Slice(2);

                clientHello.Random.CopyTo(writer);
                writer = writer.Slice(Hazel.Dtls.Random.Size);

                // Do not encode session ids
                writer[0] = (byte)0;
                writer    = writer.Slice(1);

                writer[0] = (byte)clientHello.Cookie.Length;
                clientHello.Cookie.CopyTo(writer.Slice(1));
                writer = writer.Slice(1 + clientHello.Cookie.Length);

                ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)clientHello.CipherSuites.Length);
                clientHello.CipherSuites.CopyTo(writer.Slice(2));
                writer = writer.Slice(2 + clientHello.CipherSuites.Length);

                // ============ Here is the corruption. writer[0] should be 1. ============
                writer[0] = 255;
                writer[1] = (byte)CompressionMethod.Null;
                writer    = writer.Slice(2);

                // Extensions size
                ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)(6 + clientHello.SupportedCurves.Length));
                writer = writer.Slice(2);

                // Supported curves extension
                ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)ExtensionType.EllipticCurves);
                ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)(2 + clientHello.SupportedCurves.Length), 2);
                ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)clientHello.SupportedCurves.Length, 4);
                clientHello.SupportedCurves.CopyTo(writer.Slice(6));

                return(writer);
            }
Esempio n. 16
0
        /// <summary>
        /// Reads the TLS Client Hello from the tcp stream, parsing out the server name provided by the Server Name extension. Returns a stream that behaves as if nothing had been read.
        /// </summary>
        /// <param name="tcpStream">The stream that is expected to begin a TLS 1.0, 1.1, or 1.2 handshake.</param>
        /// <param name="serverName">The server name from the TLS Server Name extension.  Or null.</param>
        /// <returns></returns>
        /// <exception cref="Exception">Throws if there is a problem parsing the TLS Client Hello.</exception>
        public static Stream Read(Stream tcpStream, out string serverName)
        {
            UnreadableStream unread = new UnreadableStream(tcpStream);

            FragmentStream readerOfClientHello = new FragmentStream(() =>
            {
                TLSPlaintext fragment = new TLSPlaintext(tcpStream);
                unread.Unread(fragment.data_header);
                unread.Unread(fragment.data_fragment);

                if (fragment.type != ContentType.handshake)
                {
                    throw new Exception("TLS protocol error: Fragment began with byte " + (byte)fragment.type + ". Expected " + (byte)ContentType.handshake);
                }
                if (!fragment.version.IsSupported())
                {
                    throw new Exception("Unsupported TLS protocol version: " + fragment.version);
                }

                return(fragment);
            });

            HandshakeMessage firstHandshakeMessage = new HandshakeMessage(new BasicDataStream(readerOfClientHello));

            if (firstHandshakeMessage.msg_type == HandshakeType.client_hello)
            {
                ClientHello clientHello = firstHandshakeMessage.body as ClientHello;
                serverName = clientHello.serverName;
            }
            else
            {
                serverName = null;
            }

            return(unread);
        }
Esempio n. 17
0
        public async Task Handshake()
        {
            var client_hello = new ClientHello()
            {
                HumanReadableName = HumanReadableName,
                Name         = Name,
                Version      = Version,
                License      = License,
                Capabilities = Capabilities.ToList()
            };

            await Connection.Send(client_hello);

            var server_hello = await Connection.Receive();

            if (!(server_hello is ServerHello))
            {
                throw new Exception($"Expected ServerHello, received {server_hello?.GetType()}");
            }

            await RegisterCommands();

            Connected.Set();
        }
Esempio n. 18
0
        //[Fact]
        public void Test1()
        {
            var buff  = new byte[PacketBuffer.MaxPacketSize];
            var pBuff = Utils.ParseHexString("060040f1010000ed0303ebf8fa56f12939b9584a3896472ec40bb863cfd3e86804fe3a47f06a2b69484c00000413011302010000c000000010000e00000b6578616d706c652e636f6dff01000100000a00080006001d0017001800100007000504616c706e000500050100000000003300260024001d00209370b2c9caa47fbabaf4559fedba753de171fa71f50f1ce15d43e994ec74d748002b0003020304000d0010000e0403050306030203080408050806002d00020101001c00024001ffa500320408ffffffffffffffff05048000ffff07048000ffff0801100104800075300901100f088394c8f03e51570806048000ffff");
            var hBuff = Utils.ParseHexString("c3ff000020088394c8f03e5157080000449e00000002");

            Array.Resize(ref pBuff, 1162);
            Array.Copy(hBuff, buff, hBuff.Length);
            Array.Copy(pBuff, 0, buff, hBuff.Length, pBuff.Length);
            Array.Resize(ref buff, hBuff.Length + pBuff.Length);

            var encryptedBuff = new byte[PacketBuffer.MaxPacketSize];
            var aead          = Cipher.TLS_AES_128_GCM_SHA256.CreateAead(Utils.ParseHexString("6b26114b9cba2b63a9e8dd4f"), Utils.ParseHexString("175257a31eb09dea9366d8bb79ad80ba"));
            //var token = aead.StartEncryption(pBuff, encryptedBuff);
            //token.UseSequenceNumber(2);
            //token.UseAssociatedData(hBuff);
            //aead.Finish(token);
            //var encryptedHex = Utils.ToHexString(token.Result.ToArray());

            var c    = new MemoryCursor(buff);
            var res1 = InitialPacket.TryParse(c, out var p);

            using (p.Payload.SetCursor(c))
            {
                var res2 = CryptoFrame.TryParse(c, out var f);
            }
            var res3 = c.IsEnd();

            var buffer = new byte[PacketBuffer.MaxPacketSize];
            var cursor = new MemoryCursor(buffer);

            using (InitialPacket.StartWriting(
                       cursor,
                       PacketVersion.CreateByDraft(29),
                       PacketConnectionId.Generate(),
                       PacketConnectionId.Generate(),
                       PacketNumber.Initial,
                       PacketToken.Empty))
            {
                using (CryptoFrame.StartWriting(cursor, 0))
                {
                    using (ClientHello.StartWriting(cursor, HandshakeRandom.Generate(), Cipher.Supported, SessionId.Generate()))
                    {
                        using (cursor.StartSupportedGroupsWriting())
                        {
                            foreach (var group in NamedGroup.Supported.Span)
                            {
                                group.WriteBytes(cursor);
                            }
                        }

                        using (cursor.StartSignatureAlgorithmsWriting())
                        {
                            foreach (var scheme in SignatureScheme.Supported.Span)
                            {
                                scheme.WriteBytes(cursor);
                            }
                        }

                        using (cursor.StartKeySharesWriting())
                        {
                            using (KeyShareEntry.StartWriting(cursor, NamedGroup.X25519))
                            {
                                Utils.ParseHexString("358072d6365880d1aeea329adf9121383851ed21a28e3b75e965d0d2cd166254").CopyTo(cursor);
                            }
                        }

                        using (cursor.StartPskKeyExchangeModesWriting())
                        {
                            PskKeyExchangeMode.PskDheKe.WriteBytes(cursor);
                        }

                        using (cursor.StartSupportedVersionsWriting())
                        {
                            ProtocolVersion.Tls13.WriteBytes(cursor);
                        }

                        cursor.StartTransportParametersWriting().Dispose();
                    }

                    for (int i = 0; i < 1000; i++)
                    {
                        PaddingFrame.WriteBytes(cursor);
                    }
                }
            }

            var t = Utils.ParseHexString("c0ff00001d08d0076f25b832934b0841f39c4f6381d72e0044ba00060041060100010203036e3828a258f4a7488d105acd6da670a41b28c2b601c58c4530486df585ec54a6000006130213011303010000d30033004700450017004104e46de65fb3e4fa258e1f03c551fa6a4507411e09bdc32e4dc597084db1852caf9d5b783243ebc748bf644ca31e108f4fdea2c19ae3c94ad99714dfa38a6a244500000021001f00001c68747470332d746573742e6c6974657370656564746563682e636f6d0010000800060568332d3239002b0003020304000d000a00080804040304010201000a000600040017001dffa5002d050480004000070480004000040480008000080101090103010267100e0104030245c00f0841f39c4f6381d72e002d000302000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");

            var client   = new UdpClient(0);
            var endPoint = new IPEndPoint(IPAddress.Parse("52.55.120.73"), 443);

            client.Send(t, t.Length, endPoint);

            IPEndPoint ep       = null;
            var        response = client.Receive(ref ep);

            var h1 = Utils.ToHexString(response);

            cursor = new MemoryCursor(response);

            var result = InitialPacket.TryParse(cursor, out var packet);

            using (packet.Payload.SetCursor(cursor))
            {
                var h2 = Utils.ToHexString(cursor.PeekEnd().ToArray());

                CryptoFrame.TryParse(cursor, out var cryptoFrame);

                using (cryptoFrame.Data.SetCursor(cursor))
                {
                    ServerHello.TryParse(cursor, out var sh);
                }
            }

            Assert.True(true);

            //var snBuff = new byte[100];
            //var snIter = snBuff.AsSpan();
            //ServerNameExtension.WriteHostName(ref snIter, "example.ulfheim.net");
            //var snResult = Parse(snBuff.AsSpan().Slice(0, snBuff.Length - snIter.Length).ToArray());

            //var keyShareBuff = new byte[1000];
            //var keyShareSpan = keyShareBuff.AsSpan();
            //var privateKey = Parse("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f");
            //var publicKey = NamedGroup.X25519.GeneratePublicKey(privateKey);
            //KeyShareExtension.WriteClientEntry(ref keyShareSpan, NamedGroup.X25519, publicKey);
            //var keyShareData = Parse(keyShareBuff.AsSpan().Slice(0, keyShareBuff.Length - keyShareSpan.Length).ToArray());

            //var secret = Parse("ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea");
            //var hash = Parse("22844b930e5e0a59a09d5ac35fc032fc91163b193874a265236e568077378d8b");
            //var expected = Parse("976017a77ae47f1658e28f7085fe37d149d1e9c91f56e1aebbe0c6bb054bd92b");

            //var verifyData = Hash.Sha256.CreateVerifyData(secret, hash);
            //var result = verifyData.Span.SequenceEqual(expected);

            //var bytes = GetData();

            //InitialPacket.TryParse(bytes, out var initial, out var remainings);

            //CryptoFrame.TryParse(initial.Payload, out var crypto, out var afterCrypto);

            //ClientHello.TryParse(crypto.Data, out var hello, out var afterHello);

            //KeyShareExtension.TryParse(hello.Payload, out var keyShare, out var afterKeyShare);

            //var unknownBytes = UnknownExtension.SliceBytes(afterKeyShare, out var afterUnknown);

            //AlpnExtension.TryParse(afterUnknown, out var alpn, out var afterAlpn);

            //SupportedVersionExtension.TryParse(afterAlpn, out var supportedVersion, out var afterSupportedVersion);

            //SignatureAlgorithmsExtension.TryParse(afterSupportedVersion, out var signatureAlgorithms, out var afterSignatureAlgorithms);

            //SupportedGroupsExtension.TryParse(afterSignatureAlgorithms, out var supportedGroups, out var afterSupportedGroups);

            //TransportParametersExtension.TryParse(afterSupportedGroups, out var transportParametersExtension, out var afterTransportParametersExtension);

            //PskKeyExchangeModesExtension.TryParse(afterTransportParametersExtension, out var pskKeyExchangeModes, out var afterPsk);

            ////----------------------------------------------------------------

            //var buffer = new byte[65000];
            //var destination = buffer.AsSpan();

            //var initialContext = InitialPacket.StartWriting(ref destination, initial.Version, initial.DestinationConnectionId, initial.SourceConnectionId, initial.Number, initial.Token);
            //var cryptoContext = CryptoFrame.StartWriting(ref destination, 0);
            //var clientHelloContext = ClientHello.StartWriting(ref destination, hello.Random, hello.CipherSuite, hello.SessionId);

            //keyShare.WriteBytes(ref destination);

            //unknownBytes.Span.CopyTo(destination);
            //destination = destination.Slice(unknownBytes.Length);

            //alpn.WriteBytes(ref destination);

            //supportedVersion.WriteBytes(ref destination);

            //signatureAlgorithms.WriteBytes(ref destination);

            //supportedGroups.WriteBytes(ref destination);

            //var transportParametersContext = TransportParametersExtension.StartWriting(ref destination);
            //transportParametersExtension.Data.Span.CopyTo(destination);
            //destination = destination.Slice(transportParametersExtension.Data.Length);
            //transportParametersContext.Complete(ref destination);

            //pskKeyExchangeModes.WriteBytes(ref destination);

            //clientHelloContext.Complete(ref destination);
            //cryptoContext.Complete(ref destination);

            //for (int i = 0; i < 1000; i++)
            //{
            //    PaddingFrame.WriteBytes(ref destination);
            //}

            //initialContext.Complete(ref destination);

            ////----------------------------------------------------------------

            //InitialPacket.TryParse(buffer.ToArray(), out var initial1, out var remainings1);

            //CryptoFrame.TryParse(initial1.Payload, out var crypto1, out var afterCrypto1);

            //ClientHello.TryParse(crypto1.Data, out var hello1, out var afterHello1);

            //KeyShareExtension.TryParse(hello1.Payload, out var keyShare1, out var afterKeyShare1);

            //var unknownBytes1 = UnknownExtension.SliceBytes(afterKeyShare1, out var afterUnknown1);

            //AlpnExtension.TryParse(afterUnknown1, out var alpn1, out var afterAlpn1);

            //SupportedVersionExtension.TryParse(afterAlpn1, out var supportedVersion1, out var afterSupportedVersion1);

            //SignatureAlgorithmsExtension.TryParse(afterSupportedVersion1, out var signatureAlgorithms1, out var afterSignatureAlgorithms1);

            //SupportedGroupsExtension.TryParse(afterSignatureAlgorithms1, out var supportedGroups1, out var afterSupportedGroups1);

            //TransportParametersExtension.TryParse(afterSupportedGroups1, out var transportParametersExtension1, out var afterTransportParametersExtension1);

            //PskKeyExchangeModesExtension.TryParse(afterTransportParametersExtension1, out var pskKeyExchangeModes1, out var afterPsk1);

            //var client = DatagramChannel.Start(opt =>
            //{
            //    opt.ListeningPoint = new IPEndPoint(IPAddress.Any, 50000);
            //});

            //var addr = Dns.GetHostAddresses("litespeedtech.com"); //443
            ////var addr = Dns.GetHostAddresses("test.privateoctopus.com"); //4433
            ////var addr = Dns.GetHostAddresses("quant.eggert.org"); //4433
            ////var addr = Dns.GetHostAddresses("f5quic.com"); //4433

            //var dgram = new Datagram().WithAddress(addr[0]).WithPort(443).WithBuffer(buffer.ToArray());

            //client.Writer.TryWrite(dgram);

            //var response = client.Reader.ReadAsync().AsTask().Result;
        }
Esempio n. 19
0
        public void Read_ResultsAreExpected()
        {
            //Arrange
            var messageBytes      = Utils.ParseHexString(GetMessageHexString());
            var record            = new TlsRecord();
            var message           = new ClientHello();
            var serverNames       = new List <ServerNameEntry>();
            var namedGroups       = new List <NamedGroup>();
            var signatureSchemes  = new List <SignatureScheme>();
            var keyShareEntries   = new List <KeyShareEntry>();
            var pskModes          = new List <PskKeyExchangeMode>();
            var supportedVersions = new List <ProtocolVersion>();
            var ciphers           = new List <Cipher>();

            //Act
            var cursor = new MemoryCursor(messageBytes);
            var result = TlsRecord.TryParse(cursor, RecordType.Handshake, out record);

            using (record.Payload.SetCursor(cursor))
            {
                result &= ClientHello.TryParse(cursor, out message);

                foreach (var cipher in message.CipherSuite)
                {
                    ciphers.Add(cipher);
                }

                using (message.Payload.SetCursor(cursor))
                {
                    result &= cursor.TryParseServerNames(out var serverNamesBuffer);
                    foreach (var entry in serverNamesBuffer.GetServerNameEntryReader(cursor))
                    {
                        serverNames.Add(entry);
                    }

                    result &= cursor.TryParseSupportedGroups(out var supportedGroupsBuffer);
                    foreach (var group in supportedGroupsBuffer.GetNamedGroupReader(cursor))
                    {
                        namedGroups.Add(group);
                    }

                    result &= cursor.TryParseSignatureAlgorithms(out var signatureAlgorithmsBuffer);
                    foreach (var scheme in signatureAlgorithmsBuffer.GetSignatureSchemeReader(cursor))
                    {
                        signatureSchemes.Add(scheme);
                    }

                    result &= cursor.TryParseKeyShares(out var keySharesBuffer);
                    foreach (var entry in keySharesBuffer.GetKeyShareEntryReader(cursor))
                    {
                        keyShareEntries.Add(entry);
                    }

                    result &= cursor.TryParsePskKeyExchangeModes(out var pskModesBuffer);
                    foreach (var mode in pskModesBuffer.GetPskKeyExchangeModeReader(cursor))
                    {
                        pskModes.Add(mode);
                    }

                    result &= cursor.TryParseSupportedVersions(out var supportedVersionsBuffer);
                    foreach (var version in supportedVersionsBuffer.GetProtocolVersionReader(cursor))
                    {
                        supportedVersions.Add(version);
                    }

                    result &= cursor.IsEnd();
                }

                result &= cursor.IsEnd();
            }

            result &= cursor.IsEnd();

            //Assert
            Assert.True(result);
            Assert.Equal(RecordType.Handshake, record.Type);
            Assert.Equal(ProtocolVersion.Tls10, record.ProtocolVersion);
            Assert.Equal(HandshakeRandom.Parse(GetBytesOfRandom()), message.Random);
            Assert.Equal(SessionId.Parse(GetBytesOfSessionId()), message.SessionId);
            Assert.Equal(new[]
            {
                Cipher.TLS_AES_128_GCM_SHA256,
                Cipher.TLS_AES_256_GCM_SHA384,
                Cipher.TLS_CHACHA20_POLY1305_SHA256
            }, ciphers);
            var serverNameEntry = Assert.Single(serverNames);

            Assert.True(serverNameEntry.IsHostName());
            Assert.Equal("example.ulfheim.net", serverNameEntry.ToString());
            Assert.Equal(new[]
            {
                NamedGroup.X25519,
                NamedGroup.SECP256R1,
                NamedGroup.SECP384R1
            }, namedGroups);
            Assert.Equal(new[]
            {
                SignatureScheme.ECDSA_SECP256R1_SHA256,
                SignatureScheme.RSA_PSS_RSAE_SHA256,
                SignatureScheme.RSA_PKCS1_SHA256,
                SignatureScheme.ECDSA_SECP384R1_SHA384,
                SignatureScheme.RSA_PSS_RSAE_SHA384,
                SignatureScheme.RSA_PKCS1_SHA384,
                SignatureScheme.RSA_PSS_RSAE_SHA512,
                SignatureScheme.RSA_PKCS1_SHA512,
                SignatureScheme.RSA_PKCS1_SHA1
            }, signatureSchemes);
            var keyShareEntry = Assert.Single(keyShareEntries);

            Assert.Equal(NamedGroup.X25519, keyShareEntry.Group);
            Assert.True(GetBytesOfPublicKey().AsSpan().SequenceEqual(keyShareEntry.Key.Read(cursor).Span));
            var pskMode = Assert.Single(pskModes);

            Assert.Equal(PskKeyExchangeMode.PskDheKe, pskMode);
            var supportedVersion = Assert.Single(supportedVersions);

            Assert.Equal(ProtocolVersion.Tls13, supportedVersion);
        }
Esempio n. 20
0
        public void Write_ResultBytesAreExpected()
        {
            //Arrange
            var expectedBytes = GetMessageHexString();
            var buffer        = new byte[TlsBuffer.MaxRecordSize];
            var random        = HandshakeRandom.Parse(GetBytesOfRandom());
            var ciphers       = new[] { Cipher.TLS_AES_128_GCM_SHA256, Cipher.TLS_AES_256_GCM_SHA384, Cipher.TLS_CHACHA20_POLY1305_SHA256 };
            var sessionId     = SessionId.Parse(GetBytesOfSessionId());

            //Act
            var cursor = new MemoryCursor(buffer);

            using (TlsRecord.StartWriting(cursor, RecordType.Handshake, ProtocolVersion.Tls10))
                using (ClientHello.StartWriting(cursor, random, ciphers, sessionId))
                {
                    using (cursor.StartServerNamesWriting())
                    {
                        ServerNameEntry.WriteHostName(cursor, "example.ulfheim.net");
                    }

                    using (cursor.StartSupportedGroupsWriting())
                    {
                        NamedGroup.X25519.WriteBytes(cursor);
                        NamedGroup.SECP256R1.WriteBytes(cursor);
                        NamedGroup.SECP384R1.WriteBytes(cursor);
                    }

                    using (cursor.StartSignatureAlgorithmsWriting())
                    {
                        SignatureScheme.ECDSA_SECP256R1_SHA256.WriteBytes(cursor);
                        SignatureScheme.RSA_PSS_RSAE_SHA256.WriteBytes(cursor);
                        SignatureScheme.RSA_PKCS1_SHA256.WriteBytes(cursor);
                        SignatureScheme.ECDSA_SECP384R1_SHA384.WriteBytes(cursor);
                        SignatureScheme.RSA_PSS_RSAE_SHA384.WriteBytes(cursor);
                        SignatureScheme.RSA_PKCS1_SHA384.WriteBytes(cursor);
                        SignatureScheme.RSA_PSS_RSAE_SHA512.WriteBytes(cursor);
                        SignatureScheme.RSA_PKCS1_SHA512.WriteBytes(cursor);
                        SignatureScheme.RSA_PKCS1_SHA1.WriteBytes(cursor);
                    }

                    using (cursor.StartKeySharesWriting())
                    {
                        using (KeyShareEntry.StartWriting(cursor, NamedGroup.X25519))
                        {
                            GetBytesOfPublicKey().CopyTo(cursor);
                        }
                    }

                    using (cursor.StartPskKeyExchangeModesWriting())
                    {
                        PskKeyExchangeMode.PskDheKe.WriteBytes(cursor);
                    }

                    using (cursor.StartSupportedVersionsWriting())
                    {
                        ProtocolVersion.Tls13.WriteBytes(cursor);
                    }
                }

            //Assert
            Assert.Equal(expectedBytes, Utils.ToHexString(cursor.PeekStart().ToArray()), true);
        }
Esempio n. 21
0
        /// <summary>
        /// Handles a ClientHello packet.
        /// </summary>
        /// <param name="session">The session that sent this packet.</param>
        /// <param name="hello">The ClientHello data that was sent.</param>
        private void HandleClientHello(ClientAgentSession sender, ClientHello hello)
        {
            // Logging
            Log?.Info("Handling ClientHello from session {0}.", sender.SessionId);

            // Let's see if this client is valid...
            ClientHelloResponse response = new ClientHelloResponse
            {
                Success          = true,
                ErrorCode        = 0,
                Message          = "",
                HeartbeatTime    = Configuration.HeartbeatTime,
                ForcedEncryption = Configuration.ForceEncryption
            };

            // Get the correct wanted hash
            uint wantedHash = Configuration.Network.Hash != 0 ?
                              Configuration.Network.Hash : NetworkFile.Hash;

            // Is the client the wrong application?
            if (hello.AppName != Configuration.Application.Name)
            {
                response.Success   = false;
                response.ErrorCode = (byte)ToffeeErrorCodes.ClientHelloApplicationInvalid;
                Log?.Warning("Invalid ClientHello from session {0}. ({1})",
                             sender.SessionId, ToffeeErrorCodes.ClientHelloApplicationInvalid);
            }
            // Is the client outdated?
            else if (hello.AppVersion != Configuration.Application.Version)
            {
                response.Success   = false;
                response.ErrorCode = (byte)ToffeeErrorCodes.ClientHelloApplicationOutOfDate;
                Log?.Warning("Invalid ClientHello from session {0}. ({1})",
                             sender.SessionId, ToffeeErrorCodes.ClientHelloApplicationOutOfDate);
            }
            // Is their encryption the same as ours?
            else if ((Configuration.EncryptionKey == 0x00) && (hello.HasEncryption))
            {
                response.Success   = false;
                response.ErrorCode = (byte)ToffeeErrorCodes.ClientHelloEncryptionInvalid;
                response.Message   = "The server is not configured to have encryption.";
                Log?.Warning("Invalid ClientHello from session {0}. ({1}, {2})",
                             sender.SessionId, ToffeeErrorCodes.ClientHelloEncryptionInvalid, response.Message);
            }
            // If we force encryption, do they have encryption?
            else if ((Configuration.ForceEncryption) && (!hello.HasEncryption))
            {
                response.Success   = false;
                response.ErrorCode = (byte)ToffeeErrorCodes.ClientHelloEncryptionInvalid;
                response.Message   = "The server is configured to force encryption.";
                Log?.Warning("Invalid ClientHello from session {0}. ({1}, {2})",
                             sender.SessionId, ToffeeErrorCodes.ClientHelloEncryptionInvalid, response.Message);
            }
            // Do they have the same network hash?
            else if (hello.NetworkHash != wantedHash)
            {
                response.Success   = false;
                response.ErrorCode = (byte)ToffeeErrorCodes.ClientHelloHashInvalid;
                Log?.Warning("Invalid ClientHello from session {0}. ({1})",
                             sender.SessionId, ToffeeErrorCodes.ClientHelloHashInvalid);
            }
            else
            {
                sender.Validated = true;
                Log?.Info("ClientHello was valid! Session {0} has been validated.", sender.SessionId);
            }

            // Send the response!
            sender.Send(ToffeeOpCode.ClientHelloResponse, response);

            // Debug information
            Log?.Debug("=== Response Info ===");
            Log?.Debug("OpCode: 0x02 (ClientHelloResponse)");
            Log?.Debug("Success: {0}", response.Success);
            Log?.Debug("ErrorCode: {0}", response.ErrorCode);
            Log?.Debug("Message: {0}", response.Message);
            Log?.Debug("HeartbeatTime: {0}", response.HeartbeatTime);
            Log?.Debug("ForcedEncryption: {0}", response.ForcedEncryption);
            Log?.Debug("=====================");
            Log?.Debug("");
        }
Esempio n. 22
0
        private bool FullProtocolFromX509(ScpConfig.EncryptionMode encryptionMode, out byte[] symmetricKey, out MockedSecretarium secretarium)
        {
            // Client keys
            Assert.IsTrue(ScpConfigHelper.TryLoad("test.x509.json", out ScpConfig config));
            Assert.IsTrue(config.TryGetECDsaKey(out ECDsaCng clientECDsaKeyCng, "SecretariumTestClient256"));
            var clientPub = clientECDsaKeyCng.ExportPublicKeyRaw();

            // Client Hello
            var clientEph    = ECDHHelper.CreateCngKey();
            var clientEphCng = ECDHHelper.CreateECDiffieHellmanCngSha256(clientEph);
            var clientEphPub = clientEphCng.PublicKey();
            var clientHello  = clientEphPub;

            Assert.IsTrue(ClientHello.Parse(clientHello, out ClientHello clientHelloObj));

            // Server Hello
            secretarium = new MockedSecretarium(encryptionMode);
            secretarium.GetServerHello(clientHello, out byte[] serverHello);
            Assert.IsTrue(ServerHello.Parse(serverHello, 18, out ServerHello serverHelloObj));

            // Client ClientProofOfWork
            Assert.IsTrue(DiffieHellmanHelper.ComputeProofOfWork(serverHelloObj.proofOfWorkDetails, out byte[] proofOfWork));
            var clientProofOfWork = ByteHelper.Combine(proofOfWork.ExtendTo(32), MockedSecretarium.GenesisPubKey);

            Assert.IsTrue(ClientProofOfWork.Parse(clientProofOfWork, out ClientProofOfWork clientProofOfWorkObj));

            // Server Identity
            secretarium.GetServerIdentity(clientProofOfWork, out byte[] serverIdentity);
            Assert.IsTrue(ServerIdentity.Parse(serverIdentity, out ServerIdentity serverIdentityObj));

            // Client computes symmetric key
            symmetricKey = DiffieHellmanHelper.GetSymmetricKey(
                clientEphCng, serverIdentityObj.ephDHKey, serverIdentityObj.preMasterSecret);

            // Client Proof Of Identity
            var nonce                 = ByteHelper.GetRandom(32);
            var nonceSigned           = clientECDsaKeyCng.SignData(nonce);
            var clientProofOfIdentity = ByteHelper.Combine(nonce, clientEphPub, clientPub, nonceSigned);

            Assert.IsTrue(ClientProofOfIdentity.Parse(clientProofOfIdentity, out ClientProofOfIdentity clientProofOfIdentityObj));

            // Client Encrypts Client Proof Of Identity
            var ivOffset = ByteHelper.GetRandom(16);
            var encryptedClientProofOfIdentity = encryptionMode == ScpConfig.EncryptionMode.AESCTR
                ? clientProofOfIdentity.AesCtrEncrypt(symmetricKey, ivOffset)
                : clientProofOfIdentity.AesGcmEncryptWithOffset(symmetricKey, ivOffset);
            var encryptedClientProofOfIdentityWithIvOffset = ByteHelper.Combine(ivOffset, encryptedClientProofOfIdentity);

            // Server Checks And Sends Proof Of Identity
            Assert.IsTrue(secretarium.GetServerProofOfIdentity(
                              encryptedClientProofOfIdentityWithIvOffset, out byte[] encryptedServerProofOfIdentity));

            // Client Decrypts Server Proof Of Identity
            ivOffset = encryptedServerProofOfIdentity.Extract(0, 16);
            var serverProofOfIdentity = encryptionMode == ScpConfig.EncryptionMode.AESCTR
                ? encryptedServerProofOfIdentity.Extract(16).AesCtrDecrypt(symmetricKey, ivOffset)
                : encryptedServerProofOfIdentity.Extract(16).AesGcmDecryptWithOffset(symmetricKey, ivOffset);

            Assert.IsTrue(ServerProofOfIdentity.Parse(serverProofOfIdentity, out ServerProofOfIdentity serverProofOfIdentityObj));

            // Client Checks Server Proof Of Idendity
            var msg = "Hey you! Welcome to Secretarium!".ToBytes();
            var secretariumECDsaCng = ECDsaHelper.ImportPublicKey(serverIdentityObj.publicKey);

            Assert.IsTrue(secretariumECDsaCng.VerifyData(
                              ByteHelper.Combine(serverProofOfIdentityObj.nonce, msg), serverProofOfIdentityObj.welcomeSigned));

            return(true);
        }
Esempio n. 23
0
        /// <summary>
        /// <exception cref="IOException"/>
        /// <exception cref="SpotifyAuthenticatedException"/>
        /// <exception cref="AccessViolationException"/>
        /// </summary>
        private void Connect()
        {
            #region ClientHello Setup

            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            var clientHello = new ClientHello
            {
                BuildInfo = new BuildInfo
                {
                    Platform     = Platform.Win32X86,
                    Product      = Product.Client,
                    ProductFlags = { ProductFlags.ProductFlagNone },
                    Version      = 112800721
                }
            };
            clientHello.CryptosuitesSupported.Add(Cryptosuite.Shannon);
            clientHello.LoginCryptoHello = new LoginCryptoHelloUnion
            {
                DiffieHellman = new LoginCryptoDiffieHellmanHello
                {
                    Gc = ByteString.CopyFrom(keys.PublicKeyArray()),
                    ServerKeysKnown = 1
                }
            };

            var nonce = new byte[16];
            (new Random()).NextBytes(nonce);
            clientHello.ClientNonce = ByteString.CopyFrom(nonce);
            clientHello.Padding     = ByteString.CopyFrom(new byte[1]
            {
                (byte)30
            });

            var clientHelloBytes = clientHello.ToByteArray();

            var a = conn.Result.NetworkStream;
            a.WriteByte(0x00);
            a.WriteByte(0x04);
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            a.Flush();

            var length = 2 + 4 + clientHelloBytes.Length;
            var bytes  = BitConverter.GetBytes(length);
            a.WriteByte(bytes[0]);
            a.Write(clientHelloBytes, 0, clientHelloBytes.Length);
            a.Flush();
            var buffer = new byte[1000];
            var len    = int.Parse(a.Read(buffer, 0, buffer.Length).ToString());
            var tmp    = new byte[len];
            Array.Copy(buffer, tmp, len);

            tmp = tmp.Skip(4).ToArray();
            var accumulator = new MemoryStream();
            accumulator.WriteByte(0x00);
            accumulator.WriteByte(0x04);

            var lnarr = Utils.toByteArray(length);
            accumulator.Write(lnarr, 0, lnarr.Length);
            accumulator.Write((byte[])clientHelloBytes, 0, clientHelloBytes.Length);

            var lenArr = Utils.toByteArray(len);
            accumulator.Write(lenArr, 0, lenArr.Length);
            accumulator.Write((byte[])tmp, 0, tmp.Length);

            #endregion ClientHello Setup

            //Read APResponseMessage

            #region APResponse

            var binaryData        = accumulator.ToArray();
            var apResponseMessage = APResponseMessage.Parser.ParseFrom(tmp);
            var sharedKey         = Utils.toByteArray(keys.ComputeSharedKey(apResponseMessage
                                                                            .Challenge.LoginCryptoChallenge.DiffieHellman.Gs.ToByteArray()));

            // Check gs_signature
            var rsa        = new RSACryptoServiceProvider();
            var rsaKeyInfo = new RSAParameters
            {
                Modulus  = new BigInteger(1, serverKey).ToByteArrayUnsigned(),
                Exponent = BigInteger.ValueOf(65537).ToByteArrayUnsigned()
            };

            //Set  to the public key values.

            //Import key parameters into RSA.
            rsa.ImportParameters(rsaKeyInfo);
            var gs   = apResponseMessage.Challenge.LoginCryptoChallenge.DiffieHellman.Gs.ToByteArray();
            var sign = apResponseMessage.Challenge.LoginCryptoChallenge.DiffieHellman.GsSignature.ToByteArray();

            if (!rsa.VerifyData(gs,
                                sign,
                                HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1))
            {
                throw new AccessViolationException("Failed to verify APResponse");
            }

            // Solve challenge
            binaryData     = accumulator.ToArray();
            using var data = new MemoryStream();
            var mac = new HMACSHA1(sharedKey);
            mac.Initialize();
            for (var i = 1; i < 6; i++)
            {
                mac.TransformBlock(binaryData, 0, binaryData.Length, null, 0);
                var temp = new[] { (byte)i };
                mac.TransformBlock(temp, 0, temp.Length, null, 0);
                mac.TransformFinalBlock(new byte[0], 0, 0);
                var final = mac.Hash;
                data.Write(final, 0, final.Length);
                mac = new HMACSHA1(sharedKey);
            }

            var dataArray = data.ToArray();
            mac = new HMACSHA1(Arrays.CopyOfRange(dataArray, 0, 0x14));
            mac.TransformBlock(binaryData, 0, binaryData.Length, null, 0);
            mac.TransformFinalBlock(new byte[0], 0, 0);
            var challenge = mac.Hash;
            var clientResponsePlaintext = new ClientResponsePlaintext
            {
                LoginCryptoResponse = new LoginCryptoResponseUnion
                {
                    DiffieHellman = new LoginCryptoDiffieHellmanResponse
                    {
                        Hmac = ByteString.CopyFrom(challenge)
                    }
                },
                PowResponse    = new PoWResponseUnion(),
                CryptoResponse = new CryptoResponseUnion()
            };
            var clientResponsePlaintextBytes = clientResponsePlaintext.ToByteArray();
            len = 4 + clientResponsePlaintextBytes.Length;
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            var bytesb = BitConverter.GetBytes(len);
            a.WriteByte(bytesb[0]);
            a.Write(clientResponsePlaintextBytes, 0, clientResponsePlaintextBytes.Length);
            a.Flush();
            try
            {
                var scrap = new byte[4];
                conn.Result.NetworkStream.ReadTimeout = 300;
                var read = conn.Result.NetworkStream.Read(scrap, 0, scrap.Length);
                if (read == scrap.Length)
                {
                    length = (scrap[0] << 24) | (scrap[1] << 16) | (scrap[2] << 8) | (scrap[3] & 0xFF);
                    var payload = new byte[length - 4];
                    conn.Result.NetworkStream.ReadComplete(payload, 0, payload.Length);
                    var failed = APResponseMessage.Parser.ParseFrom(payload)?.LoginFailed;
                    throw new SpotifyAuthenticatedException(failed);
                }
                else if (read > 0)
                {
                    throw new Exception("Read unknown data!");
                }
            }
            catch (Exception x)
            {
                // ignored
            }
            finally
            {
                conn.Result.NetworkStream.ReadTimeout = Timeout.Infinite;
            }

            using (authLock.Lock())
            {
                sendCipher = new Shannon();
                sendCipher.key(Arrays.CopyOfRange(data.ToArray(), 0x14, 0x34));

                recvCipher = new Shannon();
                recvCipher.key(Arrays.CopyOfRange(data.ToArray(), 0x34, 0x54));
                authLockEventWaitHandle.Set();
            }

            #endregion APResponse

            Debug.WriteLine("Connected successfully");
        }
        /// <summary>
        /// ClientHello を待ち受け、ALPN データを取得
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="protocolNames"></param>
        /// <returns></returns>
        public static bool TryGetClientAlpn(this ReadBufferedNetworkStream stream, out IReadOnlyList <string> protocolNames)
        {
            // ちゃんと Parse してから処理すれば良いんだけど、ALPN 取りたいだけなので雑……
            protocolNames = Array.Empty <string>();
            try
            {
                var         recordIndex = 0;
                var         recordData  = new List <byte>();
                ClientHello clientHello = null;

                while (recordData.Count < (clientHello != null ? clientHello.Length + 4 : int.MaxValue))
                {
                    stream.FillBuffer(recordIndex + 5);

                    var record = new TlsRecord
                    {
                        ContentType = stream[recordIndex++]
                    };
                    if (record.ContentType != 0x16)
                    {
                        return(false);    // not Handshake Record
                    }
                    record.MajorVersion = stream[recordIndex++];
                    record.MinorVersion = stream[recordIndex++];
                    record.Length       = stream.ReadBufferUInt16(recordIndex);

                    recordIndex += 2;
                    stream.FillBuffer(recordIndex + record.Length);
                    recordData.AddRange(stream.ReadBufferBytes(recordIndex, record.Length));

                    if (clientHello == null && 3 <= recordData.Count)
                    {
                        if (recordData[0] != 0x01)
                        {
                            return(false);    // not Client Hello
                        }
                        clientHello = new ClientHello
                        {
                            Length = recordData.ToUInt24(1)
                        };
                    }
                }

                clientHello.MajorVersion = recordData[4];
                clientHello.MinorVersion = recordData[5];
                if (clientHello.MajorVersion != 3 || clientHello.MinorVersion < 1)
                {
                    return(false);    // less than TLS 1.0 (SSL 3.1)
                }
                clientHello.SessionIDLength          = recordData[38];
                clientHello.CipherSuitesLength       = recordData.ToUInt16(39 + clientHello.SessionIDLength);
                clientHello.CompressionMethodsLength = recordData[41 + clientHello.SessionIDLength + clientHello.CipherSuitesLength];
                var extensionsStartIndex = 43 + clientHello.SessionIDLength + clientHello.CipherSuitesLength;
                if (clientHello.Length + 4 <= extensionsStartIndex - 2)
                {
                    return(false);    // no Extensions
                }
                clientHello.ExtensionsLength = recordData.ToUInt16(extensionsStartIndex - 2);
                var extensionsIndex = extensionsStartIndex;
                while (extensionsIndex < extensionsStartIndex + clientHello.ExtensionsLength)
                {
                    var type = recordData.ToUInt16(extensionsIndex);
                    extensionsIndex += 2;
                    var length = recordData.ToUInt16(extensionsIndex);
                    extensionsIndex += 2;
                    var data = recordData.Skip(extensionsIndex).Take(length).ToArray();
                    extensionsIndex += length;

                    if (type != 16)
                    {
                        continue;
                    }
                    var names     = new List <string>();
                    var alpnIndex = 2;  // ALPN Extension Length 何のためにあるの……
                    while (alpnIndex < length)
                    {
                        var nameLength = data[alpnIndex++];
                        var nameBytes  = new byte[nameLength];
                        Buffer.BlockCopy(data, alpnIndex, nameBytes, 0, nameLength);
                        names.Add(Encoding.ASCII.GetString(nameBytes));
                        alpnIndex += nameLength;
                    }
                    protocolNames = names.ToArray();
                    return(true);
                }
            }
            catch
            {
                return(false);
            }
            return(false);
        }
Esempio n. 25
0
        private static void ParseClientHello(BytesSegment msg, ref ClientHello ch)
        {
            var cur = 0;

            if (msg[cur] != 1)
            {
                throw new Exception("Expected client hello (1), got " + msg[cur]);
            }
            cur++;
            var msgLength = msg[cur] << 16 | msg[cur + 1] << 8 | msg[cur + 2]; cur += 3;

            msg.SubSelf(4); cur = 0;

            ch.Version = (ushort)(msg[cur] << 8 | msg[cur + 1]); cur += 2;

            cur += 32;                                 // skip random
            cur += 1 + msg[cur];                       // skip session_id
            cur += 2 + (msg[cur] << 8 | msg[cur + 1]); // skip cipher_suites
            cur += 1 + msg[cur];                       // skip compression_methods
            if (cur >= msgLength)
            {
                throw new Exception("extensionsBegin >= msgLength");
            }

            var extensionsLength = msg[cur] << 8 | msg[cur + 1]; cur += 2;
            var extensionsEnd    = cur + extensionsLength;

            if (extensionsEnd > msgLength)
            {
                throw new Exception("extensionsEnd > msgLength");
            }
            while (cur < extensionsEnd)
            {
                var extType = (msg[cur] << 8 | msg[cur + 1]); cur += 2;
                var extLen  = (msg[cur] << 8 | msg[cur + 1]); cur += 2;
                var extEnd  = cur + extLen;
                if (extEnd > extensionsEnd)
                {
                    throw new Exception("extEnd > extensionsEnd");
                }
                if (extType == 0)   // server_name
                {
                    var nameListLen = (msg[cur] << 8 | msg[cur + 1]); cur += 2;
                    var nameListEnd = cur + nameListLen;
                    if (nameListEnd > extEnd)
                    {
                        throw new Exception("nameListEnd > extEnd");
                    }
                    var nameList = new List <string>();
                    if (cur < nameListEnd)   // read the first item only
                    {
                        if (msg[cur++] != 0) // name_type: host_name
                        {
                            throw new Exception("Not supported name type " + msg[cur]);
                        }
                        var nameLen = (msg[cur] << 8 | msg[cur + 1]); cur += 2;
                        if (cur + nameLen > nameListEnd)
                        {
                            throw new Exception("nameEnd > nameListEnd");
                        }
                        var str = NaiveUtils.UTF8Encoding.GetString(msg.Bytes, msg.Offset + cur, nameLen);
                        // TODO: check encoding
                        ch.Sni = str;
                    }
                }
                else if (extType == 16)     // ALPN
                {
                    var listLen = (msg[cur] << 8 | msg[cur + 1]); cur += 2;
                    var listEnd = cur + listLen;
                    if (listEnd > extEnd)
                    {
                        throw new Exception("alpnListEnd > extEnd");
                    }
                    if (cur < listEnd)   // read the first item only
                    {
                        var strLen = msg[cur++];
                        if (cur + strLen > listEnd)
                        {
                            throw new Exception("alpnStrEnd > nameListEnd");
                        }
                        ch.Alpn = Encoding.ASCII.GetString(msg.Bytes, msg.Offset + cur, strLen);
                    }
                }
                else if (extType == 43)     // supported_versions
                {
                    var listLen = msg[cur++];
                    if (listLen < 2)
                    {
                        throw new Exception("listLen < 2");
                    }
                    var listEnd = cur + listLen;
                    if (listEnd > extEnd)
                    {
                        throw new Exception("supported_versions listEnd > extEnd");
                    }
                    while (cur < listEnd)
                    {
                        var ver = (ushort)(msg[cur] << 8 | msg[cur + 1]); cur += 2;
                        if (ver > ch.Version)
                        {
                            ch.Version = ver;
                        }
                    }
                }
                cur = extEnd;
            }
            return;
        }
Esempio n. 26
0
        public async Task <ServerHello> GetServerHello(ClientHello clientHello)
        {
            var result = await this.sessionService.CreateSession(clientHello);

            return(result);
        }
Esempio n. 27
0
        static void Main()
        {
            LibTLSClient      cSSL;
            Common            cf;
            Encryption        e;
            Cipher            c;
            ClientHello       clientHello;
            ClientKeyExchange cke;

            int    debug   = 0;
            String request = "";

            string[] args = Environment.GetCommandLineArgs();

            try
            {
                debug = (int)UInt32.Parse(args[4]);

                if (debug == 1)
                {
                    Console.WriteLine("Server: {0} Port: {1} Cipher: {2} Debug: {3}", args[1], args[2], args[3], args[4]);
                }
                request = args[5];
                cf      = new Common(debug);

                e    = new Encryption();
                cSSL = new LibTLSClient(cf, e);

                cSSL.cipher    = UInt32.Parse(args[3], System.Globalization.NumberStyles.HexNumber);
                c              = new Cipher((ushort)cSSL.cipher);
                cSSL.cipherObj = c;
                cSSL.serverIP  = args[1];
            }
            catch (Exception ex)
            {
                Console.WriteLine("<prog> <ip/fqdn> <port> <cipher hex> <debug [0/1/2]> <a GET request>");
                Console.WriteLine("Example: TLSClient.exe 10.209.113.104 443 002f 2 \"GET / HTTP/1.1\"");
                return;
            }

            if (c.Supported() == false)
            {
                Console.WriteLine("Cipher Suite not supported currently");
                Console.WriteLine("Please try 002f/0035/003c/003d/009c/009d");
                return;
            }

            cSSL.CreateTCPConn(args[1], Convert.ToInt32(args[2]));
            cf.HandleResult(cSSL.errorCode, "TCP Connection");
            cf.ExitOnError(cSSL.errorCode);

            cSSL.InitBufs();

            List <UInt32> cipher_suites = new List <UInt32>();

            cipher_suites.Add(cSSL.cipher);

            String clientIP = cSSL.GetIPAddress();
            String serverIP = cSSL.serverIP;

            clientHello = new ClientHello(clientIP, serverIP, 3, 3, false, cipher_suites);

            List <byte> chello_hs = clientHello.Get();

            List <byte> crandom = clientHello.GetRandom();

            cSSL.StoreClientHelloParams(crandom);

            cSSL.SendHandshakeMessage(chello_hs, 0x1);
            cf.ExitOnError(cSSL.errorCode);

            cSSL.ReceiveHandshakeMessage();
            cf.ExitOnError(cSSL.errorCode);

            cSSL.ParseServerHandshakeMessages();
            cf.ExitOnError(cSSL.errorCode);

            if (cSSL.HasServerKeyExchange())
            {
                cke = new ClientKeyExchange(cf, cSSL.sCert_hs, 3, 3, cSSL.sKeyExch_hs, (String)"ECDHE");
            }
            else
            {
                cke = new ClientKeyExchange(cf, cSSL.sCert_hs, 3, 3, null, (String)"RSA");
            }

            List <byte> cke_hs = cke.CreateCKE();

            cSSL.StoreCKEParams(cke_hs, cke.GetPremasterSecret(), cke.ecdhCngClient, cke.server_pub_key, cke.client_pub_key);

            cSSL.SendHandshakeMessage(cke_hs, 0x10);
            cf.ExitOnError(cSSL.errorCode);

            cSSL.PrintHandshakeMessages();

            cSSL.SendChangeCipherSpec();

            cSSL.ComputeMasterSecret();
            cSSL.ComputeVerifyData();
            cSSL.ComputeKeys();

            cSSL.SendClientFinished();
            cSSL.ReadServerFinished();
            cf.debugPrint(cSSL.ErrorCodeToString(cSSL.errorCode));

            if (cSSL.errorCode != 0)
            {
                return;
            }
            cSSL.SendHTTPSData(request);

            cSSL.ReadHTTPSData();
            cf.debugPrint(cSSL.ErrorCodeToString(cSSL.errorCode));
            cSSL.ParseHTTPSData();

            byte[] dec = cSSL.DecryptResp();

            String dec_s = Encoding.ASCII.GetString(dec, 0, dec.Length);

            if ((dec_s.IndexOf("HTTP") == 0) && (debug == 0))
            {
                Console.WriteLine("{0} Successful", cSSL.cipherObj.cipher_name);
            }

            if ((debug == 2) || (debug == 1))
            {
                Console.WriteLine(dec_s);
            }
        }
Esempio n. 28
0
        void ProcessHandshake()
        {
            ClientHello clientHello = _recordLayer.Read() as ClientHello;

            if (clientHello == null)
            {
                throw new Exception();
            }
            Console.WriteLine("[TLSServer] Receive ClientHello Version: {0}", clientHello.Version);
            Console.WriteLine("[TLSServer] CipherSuites");
            for (int i = 0; i < clientHello.CipherSuites.Length; i++)
            {
                Console.WriteLine("  {0}", clientHello.CipherSuites[i]);
            }
            CipherSuite selected = _selector.Select(clientHello.CipherSuites);

            Console.WriteLine("[TLSServer] CipherSuite Selected. {0}", selected);
            if (selected == CipherSuite.NONE)
            {
                // Alertを送るべき?
                throw new Exception();
            }
            CipherSuiteInfo selectedInfo = SupportedCipherSuites.GetSuiteInfo(selected);

            _sparams.SetVersion(clientHello.Version);
            _sparams.SetCipherSuite(selected, _signAlgo);
            _sparams.ClientRandom        = clientHello.Random;
            _recordLayer.ProtocolVersion = clientHello.Version;

            byte[]      serverRandom     = new byte[RandomData.Size];
            Extension[] serverExtensions = null;
            if (selectedInfo.IsECC)
            {
                serverExtensions = new Extension[] { new Extension(ExtensionType.EcPointFormats, new byte[] { 1, 0 }) }
            }
            ;
            RandomData.CreateRandomData(serverRandom, 0);
            _sparams.ServerRandom = serverRandom;
            ServerHello serverHello = new ServerHello(clientHello.Version, serverRandom, Utility.EmptyByteArray, selected, CompressionMethod.Null, serverExtensions);

            _recordLayer.Write(serverHello);

            Certificate serverCert = new Certificate(_certs);

            _recordLayer.Write(serverCert);

            if (Utility.IsNeedServerKeyExchangeMessage(_states.SecurityParameters.KeyExchangeAlgorithm))
            {
                ServerKeyExchange serverExchange = new ServerKeyExchange(_sparams);
                _recordLayer.Write(serverExchange);
            }

            _recordLayer.Write(new ServerHelloDone());

            TLSMessage        msg            = _recordLayer.Read();
            ClientKeyExchange clientExchange = (ClientKeyExchange)msg;

            clientExchange.ComputeServerMasterSecret(_sparams);
            Console.WriteLine("MasterSecret");
            Utility.Dump(_sparams.MasterSecret);
            _sparams.ComputeKeyBlock();

            ChangeCipherSpec changeCipherSpec = (ChangeCipherSpec)_recordLayer.Read();

            _recordLayer.EnableReceiveCipher(_sparams.CreateServerDecryptor(), _sparams.CreateClientWriteHMAC());

            Finished finished = (Finished)_recordLayer.Read();

            Console.WriteLine("VerifyData");
            Utility.Dump(finished.VerifyData);
            Console.WriteLine("Computed VerifyData");
            byte[] verifyData = _sparams.ComputeFinishedVerifyData(false);
            Utility.Dump(verifyData);
            if (!Utility.Equals(finished.VerifyData, 0, verifyData, 0, verifyData.Length))
            {
                throw new Exception();
            }

            _recordLayer.Write(ChangeCipherSpec.Instance);
            _recordLayer.EnableSendCipher(_sparams.CreateServerEncryptor(), _sparams.CreateServerWriteHMAC());
            _recordLayer.ComputeHandshakeHash(true);
            verifyData = _sparams.ComputeFinishedVerifyData(true);
            Console.WriteLine("Finished VerifyData");
            Utility.Dump(verifyData);
            finished = new Finished(_recordLayer.ProtocolVersion, verifyData);
            _recordLayer.Write(finished);
        }