Esempio n. 1
0
        public BufLen GetPayload()
        {
            if (!AllFragmentsFound)
            {
                throw new Exception("Cannot reassemble payload without all the fragments!");
            }

            var messagesize = Fragments.Sum(f => f.Data.Length);

            const int h5inh16offset = 11;
            var       result        = new BufLen(new byte[h5inh16offset + messagesize]);

            var writer = new BufRefLen(result, h5inh16offset);

            foreach (var onef in Fragments)
            {
                writer.Write(onef.Data);
            }

            // Fake a I2NP16 header
            var exp = new I2PDate(SSUHost.SSUDateTime(result.PeekFlip32(1 + h5inh16offset)));

            result[0] = result[h5inh16offset];
            result.PokeFlip64((ulong)exp, 5);
            result.PokeFlip16((ushort)(messagesize - 5), 13);
            // Not wasting time on faking checksum

            return(result);
        }
Esempio n. 2
0
        private PeerTestState(SSUHost host, I2PRouterInfo router)
        {
            Host   = host;
            Router = router;

            Session = (SSUSession)Host.AddSession(router);
            //Session.StartPeerTest( this );
        }
Esempio n. 3
0
        private PeerTestState(SSUHost host, I2PRouterAddress addr, I2PKeysAndCert dest)
        {
            Host = host;
            Addr = addr;
            Dest = dest;

            Session = (SSUSession)Host.AddSession(addr, dest);
            //Session.StartPeerTest( this );
        }
Esempio n. 4
0
 public SSUHeader(BufRef writer, MessageTypes msgtype)
 {
     MAC = writer.ReadBufLen(16);
     IV  = writer.ReadBufLen(16);
     IV.Randomize();
     FlagBuf      = writer.ReadBufLen(1);
     MessageType  = msgtype;
     TimeStampBuf = writer.ReadBufLen(4);
     TimeStamp    = SSUHost.SSUTime(DateTime.UtcNow);
 }
Esempio n. 5
0
        public virtual SSUState DatagramReceived(BufRefLen recv, IPEndPoint RemoteEP)
        {
            // Verify the MAC
            var reader   = new BufRefLen(recv);
            var header   = new SSUHeader(reader);
            var recvencr = header.EncryptedBuf;

            var macstate = VerifyMAC(header, CurrentMACKey);

            switch (macstate)
            {
            case MACHealth.AbandonSession:
                Logging.LogTransport($"SSU {this}: Abandoning session. MAC check failed.");

                SendSessionDestroyed();
                Session.Host.ReportEPProblem(RemoteEP);
                return(null);

            case MACHealth.Missmatch:
                return(this);
            }

            // Decrypt
            Cipher.Init(false, CurrentPayloadKey.ToParametersWithIV(header.IV));
            Cipher.ProcessBytes(recvencr);

            header.SkipExtendedHeaders(reader);

            if (header.MessageType == SSUHeader.MessageTypes.SessionDestroyed &&
                CurrentPayloadKey != Session.RemoteIntroKey &&
                CurrentPayloadKey != Session.MyRouterContext.IntroKey)
            {
                Logging.LogTransport($"SSU {this}: Received SessionDestroyed.");
                SendSessionDestroyed();
                return(null);
            }

            Logging.LogDebugData($"SSU {this}: Received message: {header.MessageType}" +
                                 $": {SSUHost.SSUDateTime( header.TimeStamp )}");

            DataReceived();

            return(HandleMessage(header, reader));
        }
Esempio n. 6
0
        private void SendUnfragmentedSessionConfirmed()
        {
            var ri = new BufLen(Session.MyRouterContext.MyRouterInfo.ToByteArray());

            SendMessage(
                SSUHeader.MessageTypes.SessionConfirmed,
                Session.MACKey,
                Session.SharedKey,
                (start, writer) =>
            {
                writer.Write8((byte)((0 << 4) + 1));
                writer.WriteFlip16((ushort)ri.Length);
                writer.Write(ri);

                Session.SignOnTimeA = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow));
                writer.Write32(Session.SignOnTimeA);
                var padding = BufUtils.Get16BytePadding(Session.MyRouterContext.Certificate.SignatureLength + (writer - start));
                writer.Write(BufUtils.RandomBytes(padding));

                var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes());
                var bport = BufUtils.Flip16BL((ushort)Session.RemoteEP.Port);
#if LOG_MUCH_TRANSPORT
                Logging.LogTransport($"SSU {this}: X for signature {Request.X.Key}.");
                Logging.LogTransport($"SSU {this}: Y for signature {Request.Y.Key}.");
                Logging.LogTransport($"SSU {this}: Alice address for signature {Request.SCMessage.Address}. Port {Request.SCMessage.Port}.");
                Logging.LogTransport($"SSU {this}: Bob address for signature {baddr}. Port {bport}.");
                Logging.LogTransport($"SSU {this}: Relay tag {Request.SCMessage.RelayTag}. Signon time {(BufLen)Session.SignOnTimeA}.");
#endif

                var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey,
                                               Request.X.Key, Request.Y.Key,
                                               Request.SCMessage.Address, Request.SCMessage.Port,
                                               baddr, bport,
                                               Request.SCMessage.RelayTag, BufUtils.To32BL(Session.SignOnTimeA)
                                               );
                writer.Write(sign);

                Logging.LogTransport($"SSU {this}: {Session.RemoteEP} " +
                                     $"sending unfragmented SessionConfirmed [0x{writer - start - SSUHeader.FIXED_HEADER_SIZE:X}] bytes.");
                return(true);
            });
        }
Esempio n. 7
0
        private void SendSessionCreated()
        {
            SendMessage(
                SSUHeader.MessageTypes.SessionCreated,
                Session.MyRouterContext.IntroKey,
                Session.MyRouterContext.IntroKey,
                (start, writer) =>
            {
                writer.Write(Y.Key);
                AAddr = Session.RemoteEP.Address.GetAddressBytes();
                writer.Write8((byte)AAddr.Length);
                writer.Write(AAddr);
                APort = BufUtils.Flip16((ushort)Session.RemoteEP.Port);
                writer.Write16(APort);
                writer.WriteFlip32(RelayTag);
                Session.SignOnTimeB = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow));
                writer.Write32(Session.SignOnTimeB);

                var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey,
                                               Request.X, Y.Key,
                                               new BufLen(AAddr), BufUtils.To16BL(APort),
                                               Request.Address, BufUtils.Flip16BL((ushort)Session.MyRouterContext.UDPPort),
                                               BufUtils.To32BL(RelayTag), BufUtils.To32BL(Session.SignOnTimeB));

                var signstart = new BufLen(writer);
                writer.Write(sign);
                var padding = BufUtils.Get16BytePadding(writer - signstart);
                writer.Write(BufUtils.RandomBytes(padding));

                var cipher       = new CbcBlockCipher(new AesEngine());
                var signcryptbuf = new BufLen(signstart, 0, writer - signstart);
                cipher.Init(true, Session.SharedKey.ToParametersWithIV(new BufLen(start, 16, 16)));
                cipher.ProcessBytes(signcryptbuf);
                return(true);
            });
        }
Esempio n. 8
0
        public override SSUState HandleMessage(SSUHeader header, BufRefLen reader)
        {
            var tstime = SSUHost.SSUDateTime(header.TimeStamp);

            if (header.MessageType != SSUHeader.MessageTypes.SessionCreated)
            {
                Logging.LogTransport($"SSU SessionRequestState: Received unexpected message {tstime} : {header.Flag}");
                return(this);
            }

            SCMessage = new SessionCreated(reader, Session.RemoteRouter.Certificate);

            Session.RelayTag = SCMessage.RelayTag;

            Y = new I2PPublicKey((BufRefLen)SCMessage.Y, Session.RemoteRouter.Certificate);
            BufUtils.DHI2PToSessionAndMAC(out var sessionkey, out var mackey,
                                          Y.ToBigInteger().ModPow(PrivateKey.ToBigInteger(), I2PConstants.ElGamalP));

            Session.SharedKey = sessionkey;
            Session.MACKey    = mackey;

            var    ipaddr = new IPAddress(SCMessage.Address.ToByteArray());
            ushort port   = SCMessage.Port.PeekFlip16(0);

            Session.SignOnTimeB = SCMessage.SignOnTime.Peek32(0);
            var btime = SSUHost.SSUDateTime(BufUtils.Flip32(Session.SignOnTimeB));

            Logging.LogTransport($"SSU SessionRequestState {Session.DebugId} : Received SessionCreated. {tstime.ToString()} : {btime}");
            Session.Host.ReportedAddress(ipaddr);

            if (!I2PSignature.SupportedSignatureType(Session.RemoteRouter.Certificate.SignatureType))
            {
                throw new SignatureCheckFailureException($"SSU SessionRequestState {Session.DebugId} : " +
                                                         $"Received non supported signature type: " +
                                                         $"{Session.RemoteRouter.Certificate.SignatureType}");
            }

            var cipher = new CbcBlockCipher(new AesEngine());

            cipher.Init(false, Session.SharedKey.ToParametersWithIV(header.IV));
            cipher.ProcessBytes(SCMessage.SignatureEncrBuf);

            var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes());
            var sign  = new I2PSignature((BufRefLen)SCMessage.Signature, Session.RemoteRouter.Certificate);

            var sok = I2PSignature.DoVerify(
                Session.RemoteRouter.SigningPublicKey, sign,
                X.Key, Y.Key,
                SCMessage.Address, SCMessage.Port,
                baddr, BufUtils.Flip16BL((ushort)Session.RemoteEP.Port),
                SCMessage.RelayTag, SCMessage.SignOnTime);

            Logging.LogTransport($"SSU SessionRequestState: Signature check: {sok}. {Session.RemoteRouter.Certificate.SignatureType}");

            if (!sok)
            {
                throw new SignatureCheckFailureException($"SSU SessionRequestState {Session.DebugId}: Received SessionCreated signature check failed." +
                                                         Session.RemoteRouter.Certificate.ToString());
            }

            if (!RemoteIsFirewalled)
            {
                var relaytag = SCMessage.RelayTag.PeekFlip32(0);
                if (relaytag != 0)
                {
                    Session.RemoteIntroducerInfo = new IntroducerInfo(
                        Session.RemoteEP.Address,
                        (ushort)Session.RemoteEP.Port,
                        Session.RemoteIntroKey, relaytag);

                    Session.Host.IntroductionRelayOffered(Session.RemoteIntroducerInfo);
                }
            }

            Logging.LogTransport($"SSU {this}: SessionCreated received " +
                                 $"from {Session.RemoteEP} created. Moving to SessionConfirmedState.");

            Session.ReportConnectionEstablished();

            return(new SessionConfirmedState(Session, this));
        }
Esempio n. 9
0
        private void SendFragmentedSessionConfirmed()
        {
            var ri       = new BufLen(Session.MyRouterContext.MyRouterInfo.ToByteArray());
            var rireader = new BufRefLen(ri);

            var datafragments = new List <BufLen>();

            while (rireader.Length > 0)
            {
                datafragments.Add(rireader.ReadBufLen(Math.Min(rireader.Length, 472)));
            }

            for (int i = 0; i < datafragments.Count; ++i)
            {
                Logging.LogTransport($"SSU {this}: {Session.RemoteEP} " +
                                     $"sending fragment {i + 1} of {datafragments.Count + 1}, [0x{datafragments[i].Length:X}] bytes.");

                SendMessage(
                    SSUHeader.MessageTypes.SessionConfirmed,
                    Session.MACKey,
                    Session.SharedKey,
                    (start, writer) =>
                {
                    writer.Write8((byte)((i << 4) + datafragments.Count + 1));
                    writer.WriteFlip16((ushort)datafragments[i].Length);
                    writer.Write(datafragments[i]);

                    return(true);
                });
            }

            SendMessage(
                SSUHeader.MessageTypes.SessionConfirmed,
                Session.MACKey,
                Session.SharedKey,
                (start, writer) =>
            {
                var frag = datafragments.Count;
                writer.Write8((byte)((frag << 4) + frag + 1));
                writer.WriteFlip16(0);

                Session.SignOnTimeA = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow));
                writer.Write32(Session.SignOnTimeA);
                var padding = BufUtils.Get16BytePadding(Session.MyRouterContext.Certificate.SignatureLength + (writer - start));
                writer.Write(BufUtils.RandomBytes(padding));

                var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes());

                var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey,
                                               Request.X.Key, Request.Y.Key,
                                               Request.SCMessage.Address, Request.SCMessage.Port,
                                               baddr, BufUtils.Flip16BL((ushort)Session.RemoteEP.Port),
                                               Request.SCMessage.RelayTag, BufUtils.To32BL(Session.SignOnTimeA)
                                               );
                writer.Write(sign);

                Logging.LogTransport($"SSU {this}: {Session.RemoteEP} " +
                                     $"sending fragment {frag + 1} of {datafragments.Count + 1}, [0x{writer - start - SSUHeader.FIXED_HEADER_SIZE:X}] bytes.");

                return(true);
            });
        }