private SSUState AssembleFragments(SSUHeader header, BufRefLen reader, byte info, ushort cursize)
        {
            var fragnr    = info >> 4;
            var fragcount = info & 0x0f;

            if (fragnr == fragcount - 1)
            {
                ASignonTime = reader.Read32();
                reader.Seek(reader.Length - Session.RemoteRouter.Certificate.SignatureLength);
                ASign = new I2PSignature(reader, Session.RemoteRouter.Certificate);
            }
            else
            {
                Fragments[fragnr] = reader.ReadBufLen(cursize);
            }

            if (Fragments.Any(f => f == null))
            {
                return(this);
            }

            Session.RemoteRouter = new I2PRouterIdentity(new BufRefLen(Fragments.SelectMany(f => f.ToByteArray()).ToArray()));

            return(VerifyRemoteSignature());
        }
Exemple #2
0
        internal static BufLen Send(DHHandshakeContext context)
        {
            context.TimestampA = (uint)Math.Ceiling((DateTime.UtcNow - I2PDate.RefDate).TotalSeconds);

            var cleartext = new BufRefStream();
            var ri        = RouterContext.Inst.MyRouterIdentity.ToByteArray();

            cleartext.Write(BufUtils.Flip16B((ushort)ri.Length));
            cleartext.Write(ri);

            cleartext.Write(BufUtils.Flip32B(context.TimestampA));

            Logging.LogDebugData($"SessionConfirmA send TimestampA: {I2PDate.RefDate.AddSeconds( context.TimestampA )}");
            Logging.LogDebugData($"SessionConfirmA send TimestampB: {I2PDate.RefDate.AddSeconds( context.TimestampB )}");

            var sign = I2PSignature.DoSign(RouterContext.Inst.PrivateSigningKey,
                                           context.X.Key,
                                           context.Y.Key,
                                           context.RemoteRI.IdentHash.Hash,
                                           BufUtils.Flip32BL(context.TimestampA),
                                           BufUtils.Flip32BL(context.TimestampB));

            var padsize = BufUtils.Get16BytePadding((int)(sign.Length + cleartext.Length));

            cleartext.Write(BufUtils.RandomBytes(padsize));

            cleartext.Write(sign);

            var buf = new BufLen(cleartext.ToArray());

            context.Encryptor.ProcessBytes(buf);

            return(buf);
        }
Exemple #3
0
        internal static void Receive(DHHandshakeContext context, I2PKeysAndCert ri)
        {
            var responselength = ri.Certificate.SignatureLength;

            responselength += BufUtils.Get16BytePadding(responselength);

            var data = context.Client.BlockReceive(responselength);

            context.Dectryptor.ProcessBytes(data);

            var signature = new I2PSignature(new BufRefLen(data), context.RemoteRI.Certificate);

            if (!I2PSignature.SupportedSignatureType(context.RemoteRI.Certificate.SignatureType))
            {
                throw new SignatureCheckFailureException("NTCP SessionConfirmB recv not supported signature type: " +
                                                         context.RemoteRI.Certificate.SignatureType.ToString());
            }

            var ok = I2PSignature.DoVerify(context.RemoteRI.SigningPublicKey, signature,
                                           context.X.Key,
                                           context.Y.Key,
                                           RouterContext.Inst.MyRouterIdentity.IdentHash.Hash,
                                           BufUtils.Flip32BL(context.TimestampA),
                                           BufUtils.Flip32BL(context.TimestampB));

#if LOG_ALL_TRANSPORT
            DebugUtils.Log("SessionConfirmB: " + context.RemoteRI.Certificate.SignatureType.ToString() + " signature check: " + ok.ToString());
#endif
            if (!ok)
            {
                throw new SignatureCheckFailureException("NTCP SessionConfirmB recv sig check failure");
            }
        }
Exemple #4
0
        internal static BufLen Send(DHHandshakeContext context)
        {
            context.TimestampA = (uint)Math.Ceiling((DateTime.UtcNow - I2PDate.RefDate).TotalSeconds);

            var cleartext = new List <byte>();
            var ri        = RouterContext.Inst.MyRouterIdentity.ToByteArray();

            cleartext.AddRange(BufUtils.Flip16B((ushort)ri.Length));
            cleartext.AddRange(ri);

            cleartext.AddRange(BufUtils.Flip32B(context.TimestampA));
#if LOG_ALL_TRANSPORT
            DebugUtils.Log("SessionConfirmA send TimestampA: " + (I2PDate.RefDate.AddSeconds(context.TimestampA).ToString()));
            DebugUtils.Log("SessionConfirmA send TimestampB: " + (I2PDate.RefDate.AddSeconds(context.TimestampB).ToString()));
#endif

            var sign = I2PSignature.DoSign(RouterContext.Inst.PrivateSigningKey,
                                           context.X.Key,
                                           context.Y.Key,
                                           context.RemoteRI.IdentHash.Hash,
                                           BufUtils.Flip32BL(context.TimestampA),
                                           BufUtils.Flip32BL(context.TimestampB));

            var padsize = BufUtils.Get16BytePadding(sign.Length + cleartext.Count);
            cleartext.AddRange(BufUtils.Random(padsize));

            cleartext.AddRange(sign);

            var buf = new BufLen(cleartext.ToArray());
            context.Encryptor.ProcessBytes(buf);

            return(buf);
        }
        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.Random(padding));

                var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes());
                var bport = BufUtils.Flip16BL((ushort)Session.RemoteEP.Port);
#if LOG_ALL_TRANSPORT
                Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: X for signature {1}.",
                                                   Session.DebugId, Request.X.Key));
                Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Y for signature {1}.",
                                                   Session.DebugId, Request.Y.Key));
                Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Alice address for signature {1}. Port {2}.",
                                                   Session.DebugId, Request.SCMessage.Address, Request.SCMessage.Port));
                Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Bob address for signature {1}. Port {2}.",
                                                   Session.DebugId, baddr, bport));
                Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Relay tag {1}. Signon time {2}.",
                                                   Session.DebugId, Request.SCMessage.RelayTag, (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, (BufLen)Session.SignOnTimeA
                                               );
                writer.Write(sign);

#if LOG_ALL_TRANSPORT
                Logging.LogTransport(string.Format("SessionConfirmedState {0}: sending unfragmented SessionConfirmed. {1} bytes [0x{1:X}].",
                                                   Session.DebugId,
                                                   writer - start - SSUHeader.FIXED_HEADER_SIZE));
#endif

                return(true);
            });
        }
        private SSUState VerifyRemoteSignature()
        {
            var baaddr = new BufLen(AAddr);
            var bbport = BufUtils.Flip16BL((ushort)Session.MyRouterContext.UDPPort);

#if LOG_ALL_TRANSPORT
            DebugUtils.Log(string.Format("SSU SessionCreatedState {0}: X for signature {1}.",
                                         Session.DebugId, Request.X));
            DebugUtils.Log(string.Format("SSU SessionCreatedState {0}: Y for signature {1}.",
                                         Session.DebugId, Y.Key));
            DebugUtils.Log(string.Format("SSU SessionCreatedState {0}: Alice address for signature {1}. Port {2}.",
                                         Session.DebugId, baaddr, (BufLen)APort));
            DebugUtils.Log(string.Format("SSU SessionCreatedState {0}: Bob address for signature {1}. Port {2}.",
                                         Session.DebugId, Request.Address, bbport));
            DebugUtils.Log(string.Format("SSU SessionCreatedState {0}: Relay tag {1}. Signon time {2}.",
                                         Session.DebugId, (BufLen)RelayTag, (BufLen)ASignonTime));
#endif

            var signdata = new BufLen[] {
                Request.X, Y.Key,
                baaddr, (BufLen)APort,
                Request.Address, bbport,
                (BufLen)RelayTag, (BufLen)ASignonTime
            };
            var ok = I2PSignature.DoVerify(Session.RemoteRouter.SigningPublicKey, ASign, signdata);
#if LOG_ALL_TRANSPORT
            DebugUtils.Log("SSU SessionCreatedState " + Session.DebugId + ": " +
                           Session.RemoteRouter.Certificate.SignatureType.ToString() +
                           " signature check: " + ok.ToString());
#endif
            if (!ok)
            {
                throw new SignatureCheckFailureException("SSU SessionCreatedState recv sig check failure");
            }

            DebugUtils.Log("SSU SessionCreatedState: Session " + Session.DebugId + " established. Moving to Established state.");
            var next = new EstablishedState(Session);

            Session.ReportConnectionEstablished();

            if (NetDb.Inst != null)
            {
                NetDb.Inst.Statistics.SuccessfulConnect(Session.RemoteRouter.IdentHash);
            }
            return(next);
        }
Exemple #7
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);
            });
        }
Exemple #8
0
        public StreamingPacket(BufRefLen reader)
        {
            SendStreamId    = reader.ReadFlip32();
            ReceiveStreamId = reader.ReadFlip32();
            SequenceNumber  = reader.ReadFlip32();
            AckTrhough      = reader.ReadFlip32();

            NACKs = new List <uint>();
            var nackcount = reader.Read8();

            for (int i = 0; i < nackcount; ++i)
            {
                NACKs.Add(reader.ReadFlip32());
            }

            ResendDelay = reader.Read8();

            Flags = (PacketFlags)reader.ReadFlip16();
            var optionsize = reader.ReadFlip16();

            // Options order
            // DELAY_REQUESTED
            // FROM_INCLUDED
            if ((Flags & PacketFlags.FROM_INCLUDED) != 0)
            {
                From = new I2PDestination(reader);
            }
            // MAX_PACKET_SIZE_INCLUDED
            if ((Flags & PacketFlags.MAX_PACKET_SIZE_INCLUDED) != 0)
            {
                var mtu = reader.ReadFlip16();
            }
            // OFFLINE_SIGNATURE
            // SIGNATURE_INCLUDED
            if ((Flags & PacketFlags.SIGNATURE_INCLUDED) != 0)
            {
                Signature = new I2PSignature(reader, From.Certificate);
            }

            Payload = reader.ReadBufLen(reader.Length);
        }
        private SSUState VerifyRemoteSignature()
        {
            var baaddr = new BufLen(AAddr);
            var bbport = BufUtils.Flip16BL((ushort)Session.MyRouterContext.UDPPort);

#if LOG_MUCH_TRANSPORT
            Logging.LogTransport($"SSU {this}: X for signature {Request.X}.");
            Logging.LogTransport($"SSU {this}: Y for signature {Y.Key}.");
            Logging.LogTransport($"SSU {this}: Alice address for signature {baaddr}. Port {(BufLen)APort}.");
            Logging.LogTransport($"SSU {this}: Bob address for signature {Request.Address}. Port {bbport}.");
            Logging.LogTransport($"SSU {this}: Relay tag {(BufLen)RelayTag}. Signon time {(BufLen)ASignonTime}.");
#endif

            var signdata = new BufLen[] {
                Request.X, Y.Key,
                baaddr, BufUtils.To16BL(APort),
                Request.Address, bbport,
                BufUtils.To32BL(RelayTag), BufUtils.To32BL(ASignonTime)
            };

            var ok = I2PSignature.DoVerify(Session.RemoteRouter.SigningPublicKey, ASign, signdata);

            Logging.LogTransport($"SSU SessionCreatedState {Session.DebugId}: " +
                                 $"{Session.RemoteRouter.Certificate.SignatureType} " +
                                 $"signature check: {ok}");

            if (!ok)
            {
                throw new SignatureCheckFailureException("SSU SessionCreatedState recv sig check failure");
            }

            Logging.LogTransport("SSU SessionCreatedState: Session " + Session.DebugId + " established. Moving to Established state.");
            var next = new EstablishedState(Session);

            Session.ReportConnectionEstablished();

            NetDb.Inst.Statistics.SuccessfulConnect(Session.RemoteRouter.IdentHash);
            return(next);
        }
Exemple #10
0
        private SSUState AssembleFragments(SSUHeader header, BufRefLen reader, byte info, ushort cursize)
        {
            var fragnr    = info >> 4;
            var fragcount = info & 0x0f;

            Logging.LogTransport($"AssembleFragments: frag {fragnr} / {fragcount}, len {cursize}.");

            if (fragnr != fragcount - 1)
            {
                Fragments[fragnr] = reader.ReadBufLen(cursize);
            }
            else
            {
                ASignonTime       = reader.Peek32(cursize);
                Fragments[fragnr] = reader.ReadBufLen(reader.Length);
            }

            if (Fragments.Any(f => f is null))
            {
                return(this);
            }

            var buf       = new BufLen(new byte[Fragments.Sum(f => f.Length)]);
            var bufwriter = new BufRefLen(buf);

            for (int i = 0; i < Fragments.Length; ++i)
            {
                bufwriter.Write(Fragments[i]);
            }
            Session.RemoteRouter = new I2PRouterIdentity((BufRefLen)buf);

            var signbuf = new BufRefLen(buf,
                                        buf.Length - Session.RemoteRouter.Certificate.SignatureLength);

            ASign = new I2PSignature(signbuf, Session.RemoteRouter.Certificate);

            return(VerifyRemoteSignature());
        }
Exemple #11
0
        internal static byte[] Send(DHHandshakeContext context)
        {
            var msglen = RouterContext.Inst.MyRouterIdentity.Certificate.SignatureLength;

            msglen += BufUtils.Get16BytePadding(msglen);

            var writer = new BufRefLen(new byte[msglen]);

            var SigBuf = I2PSignature.DoSign(RouterContext.Inst.PrivateSigningKey,
                                             context.XBuf,
                                             context.YBuf,
                                             context.RemoteRI.IdentHash.Hash,
                                             (BufLen)BufUtils.Flip32(context.TimestampA),
                                             (BufLen)BufUtils.Flip32(context.TimestampB));

            writer.Write(SigBuf);
            writer.Write(BufUtils.Random(writer.Length));

            writer.Reset();
            context.Encryptor.ProcessBytes((BufLen)writer);

            return(writer.ToByteArray());
        }
        private SSUState ParseSessionConfirmed(SSUHeader header, BufRefLen reader)
        {
            var info    = reader.Read8();
            var cursize = reader.ReadFlip16();

            if (Fragments != null)
            {
                return(AssembleFragments(header, reader, info, cursize));
            }

            if ((info & 0x0f) == 1)
            {
                var cursizedata = reader.ReadBufRefLen(cursize);
                Session.RemoteRouter = new I2PRouterIdentity(cursizedata);
                ASignonTime          = reader.Read32();
                reader.Seek(reader.Length - Session.RemoteRouter.Certificate.SignatureLength);
                ASign = new I2PSignature(reader, Session.RemoteRouter.Certificate);

                return(VerifyRemoteSignature());
            }

            Fragments = new List <BufLen>(new BufLen[info & 0x0f]);
            return(AssembleFragments(header, reader, info, cursize));
        }
        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), (BufLen)APort,
                                               Request.Address, (BufLen)BufUtils.Flip16((ushort)Session.MyRouterContext.UDPPort),
                                               (BufLen)RelayTag, (BufLen)Session.SignOnTimeB);

                var signstart = new BufLen(writer);
                writer.Write(sign);
                var padding = BufUtils.Get16BytePadding(writer - signstart);
                writer.Write(BufUtils.Random(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);
            });
        }
        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)
            {
#if LOG_ALL_TRANSPORT
                Logging.LogTransport(string.Format("SessionConfirmedState {0}: sending fragment {1} of {2}, {3} bytes [0x{3:X}].",
                                                   Session.DebugId,
                                                   i + 1,
                                                   datafragments.Count + 1,
                                                   datafragments[i].Length));
#endif
                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.Random(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, (BufLen)Session.SignOnTimeA
                                               );
                writer.Write(sign);

#if LOG_ALL_TRANSPORT
                Logging.LogTransport(string.Format("SessionConfirmedState {0}: sending fragment {1} of {2}, {3} bytes [0x{3:X}].",
                                                   Session.DebugId,
                                                   frag + 1,
                                                   datafragments.Count + 1,
                                                   writer - start - SSUHeader.FIXED_HEADER_SIZE));
#endif

                return(true);
            });
        }
Exemple #15
0
        internal static void Receive(DHHandshakeContext context, BufLen datastart)
        {
            var origbuf = new BufRefLen(datastart);
            var reader  = new BufRefLen(datastart);

            context.Dectryptor.ProcessBytes(datastart);

            var rilen = reader.ReadFlip16();
            var ribuf = reader.ReadBufRefLen(rilen);

            context.TimestampA = reader.ReadFlip32();
#if LOG_ALL_TRANSPORT
            DebugUtils.Log("SessionConfirmA recv TimestampA: " + (I2PDate.RefDate.AddSeconds(context.TimestampA).ToString()));
            DebugUtils.Log("SessionConfirmA recv TimestampB: " + (I2PDate.RefDate.AddSeconds(context.TimestampB).ToString()));
#endif

            context.RemoteRI = new I2PRouterIdentity(ribuf);
            context.RunContext.RemoteRouterIdentity = context.RemoteRI;

            var sizeofpayload = 2 + rilen + 4 + context.RemoteRI.Certificate.SignatureLength;
            var paddingsize   = BufUtils.Get16BytePadding(sizeofpayload);
            reader.Seek(paddingsize);

            var sigstart = new BufLen(reader, 0, context.RemoteRI.Certificate.SignatureLength);

            var needbytes = 2 + context.RemoteRI.Certificate.RouterIdentitySize + 4 + context.RemoteRI.Certificate.SignatureLength;
            needbytes += BufUtils.Get16BytePadding(needbytes);

            var writer   = new BufRef(origbuf, origbuf.Length);
            var gotbytes = writer - origbuf;

            if (gotbytes < needbytes)
            {
#if LOG_ALL_TRANSPORT
                DebugUtils.Log("SessionConfirmA recv not enough data: " + datastart.Length.ToString() + ". I want " + needbytes.ToString() + " bytes.");
#endif
                var buf = context.Client.BlockReceive(needbytes - gotbytes);
                writer.Write(buf);
            }

            if (needbytes - datastart.Length > 0)
            {
                context.Dectryptor.ProcessBytes(new BufLen(datastart, datastart.Length, needbytes - datastart.Length));
            }

            var signature = new I2PSignature(new BufRefLen(sigstart), context.RemoteRI.Certificate);

            if (!I2PSignature.SupportedSignatureType(context.RemoteRI.Certificate.SignatureType))
            {
                throw new SignatureCheckFailureException("NTCP SessionConfirmA recv not supported signature type: " +
                                                         context.RemoteRI.Certificate.SignatureType.ToString());
            }

            var sigok = I2PSignature.DoVerify(
                context.RemoteRI.SigningPublicKey,
                signature,
                context.XBuf,
                context.YBuf,
                RouterContext.Inst.MyRouterIdentity.IdentHash.Hash,
                new BufLen(BufUtils.Flip32B(context.TimestampA)),
                new BufLen(BufUtils.Flip32B(context.TimestampB))
                );

#if LOG_ALL_TRANSPORT
            DebugUtils.Log("SessionConfirmA recv: " + context.RemoteRI.Certificate.SignatureType.ToString() +
                           " signature check: " + sigok.ToString() + ".");
#endif
            if (!sigok)
            {
                throw new SignatureCheckFailureException("NTCP SessionConfirmA recv signature check fail");
            }
        }
Exemple #16
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);
            });
        }
Exemple #17
0
        public override SSUState HandleMessage(SSUHeader header, BufRefLen reader)
        {
            var tstime = SSUHost.SSUDateTime(header.TimeStamp);

            if (header.MessageType != SSUHeader.MessageTypes.SessionCreated)
            {
#if LOG_ALL_TRANSPORT
                Logging.LogTransport("SSU SessionRequestState: Received unexpected message " + tstime.ToString() + " : " + header.Flag.ToString());
#endif
                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 Session.SharedKey, out Session.MACKey,
                                          Y.ToBigInteger().ModPow(PrivateKey.ToBigInteger(), I2PConstants.ElGamalP));

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

#if LOG_ALL_TRANSPORT
            Logging.LogTransport("SSU SessionRequestState " + Session.DebugId + " : Received SessionCreated. " + tstime.ToString() + " : " + btime.ToString());
#endif
            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.ToString());
            }

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

#if LOG_ALL_TRANSPORT
            Logging.LogTransport("SSU SessionRequestState: Signature check: " + sok.ToString() + ". " + Session.RemoteRouter.Certificate.SignatureType.ToString());
#endif
            if (!sok)
            {
                throw new SignatureCheckFailureException("SSU SessionRequestState " + Session.DebugId + ": Received SessionCreated signature check failed." +
                                                         Session.RemoteRouter.Certificate.ToString());
            }

            var relaytag = SCMessage.RelayTag.PeekFlip32(0);
            if (relaytag != 0)
            {
                Session.Host.IntroductionRelayOffered(
                    new IntroducerInfo(
                        Session.RemoteEP.Address,
                        (ushort)Session.RemoteEP.Port,
                        Session.IntroKey, relaytag));
            }

            Logging.LogTransport("SSU SessionRequestState: Session " + Session.DebugId + " created. Moving to SessionConfirmedState.");
            Session.ReportConnectionEstablished();
            return(new SessionConfirmedState(Session, this));
        }
Exemple #18
0
        internal override I2CPState MessageReceived(I2CPMessage msg)
        {
            try
            {
                switch (msg)
                {
                case CreateSessionMessage csm:
                    Logging.LogDebug($"{this}: Received message {csm}.");

                    var signok = I2PSignature.DoVerify(
                        csm.Config.Destination.SigningPublicKey,
                        csm.Config.Signature,
                        csm.Config.SignedBuf);

                    if (!signok)
                    {
                        Logging.LogWarning($"{this} CreateSessionMessage: Signature check failed.");
                        Session.Send(new SessionStatusMessage(0, SessionStates.Invalid));
                        return(this);
                    }

                    var newdest = Router.CreateDestination(
                        csm.Config.Destination,
                        null,
                        !csm.Config.DontPublishLeaseSet,
                        out var alreadyrunning);

                    if (alreadyrunning || newdest is null)
                    {
                        Logging.LogWarning($"{this}: Destination already running. {csm}");
                        Session.Send(new SessionStatusMessage(0, SessionStates.Refused));
                        return(this);
                    }

                    var newsession = Session.GenerateNewSessionId();
                    newsession.MyDestination = newdest;

                    newsession.Config = csm.Config;
                    UpdateConfiguration(newsession, csm.Config);

                    Session.AttachDestination(newsession.MyDestination);

                    Logging.LogDebug($"{this}: Creating session {newsession.SessionId}.");

                    var reply = new SessionStatusMessage(newsession.SessionId, SessionStates.Created);
                    Session.Send(reply);

                    Session.SendPendingLeaseUpdates(true);
                    break;

                case ReconfigureSessionMessage rcm:
                    var rcms = Session.SessionIds[rcm.SessionId];
                    rcms.Config = rcm.Config;
                    UpdateConfiguration(rcms, rcms.Config);
                    break;

                case CreateLeaseSetMessage clsm:
                    Logging.LogDebug($"{this}: {clsm} {clsm.PrivateKey}");

                    var s = Session.SessionIds[clsm.SessionId];
                    s.PrivateKey = clsm.PrivateKey;
                    s.MyDestination.TemporaryPrivateKey = clsm.PrivateKey;

                    s.LeaseInfo = clsm.Info;
                    s.MyDestination.SignedLeases = clsm.Leases;

                    Session.SendPendingLeaseUpdates(true);
                    break;

                case DestLookupMessage dlum:
                    Logging.LogDebug($"{this}: {dlum} {dlum.Ident.Id32Short}");

                    Session
                    .SessionIds
                    .First()
                    .Value
                    .MyDestination
                    .LookupDestination(dlum.Ident, HandleDestinationLookupResult, null);
                    break;

                case HostLookupMessage hlum:
                    Logging.LogDebug($"{this}: {hlum} {hlum.SessionId} {hlum.RequestId} {hlum.Hash?.Id32Short}");

                    I2PIdentHash lookuphash;

                    if (hlum.RequestType == HostLookupMessage.HostLookupTypes.HostName)
                    {
                        lookuphash = ParseHostName(hlum);

                        if (lookuphash is null)
                        {
                            Session.Send(new HostReplyMessage(
                                             hlum.SessionId,
                                             hlum.RequestId,
                                             HostLookupResults.Failure));
                            break;
                        }
                    }
                    else
                    {
                        lookuphash = hlum.Hash;
                    }

                    if (hlum.SessionId == 0xFFFF)
                    {
                        Router.LookupDestination(
                            lookuphash,
                            HandleHostLookupResult,
                            new HostLookupInfo {
                            RequestId = hlum.RequestId, SessionId = hlum.SessionId
                        });
                    }
                    else
                    {
                        var s2 = Session.SessionIds[hlum.SessionId];

                        s2.MyDestination.LookupDestination(
                            lookuphash,
                            HandleHostLookupResult,
                            new HostLookupInfo {
                            RequestId = hlum.RequestId, SessionId = hlum.SessionId
                        });
                    }
                    break;

                case SendMessageMessage smm:
                    Logging.LogDebugData($"{this}: {smm} {smm.Destination.IdentHash.Id32Short} {smm.Payload}");

                    SendMessageToDestination(
                        smm.Destination,
                        smm.SessionId,
                        smm.Payload,
                        smm.Nonce);
                    break;

                case SendMessageExpiresMessage smem:
                    Logging.LogDebugData($"{this}: {smem} {smem.Destination.IdentHash.Id32Short} {(PayloadFormat)smem.Payload[9]} {smem.Payload}");

                    SendMessageToDestination(
                        smem.Destination,
                        smem.SessionId,
                        smem.Payload,
                        smem.Nonce);
                    break;

                case DestroySessionMessage dsm:
                    Logging.LogDebug($"{this}: {dsm}");
                    Session.Send(new SessionStatusMessage(dsm.SessionId, SessionStates.Destroyed));
                    return(null);

                default:
                    Logging.LogWarning($"{this}: Unhandled message {msg}");
                    break;
                }
                return(this);
            }
            catch (Exception ex)
            {
                Logging.LogWarning($"{this} MessageReceived: {msg.MessageType} {ex}");
                throw;
            }
        }
Exemple #19
0
        public void Write(BufRefStream dest)
        {
            // Not including options
            var headersize = 4 * 4 + 1 + NACKs.Count * 4 + 1 + 2 + 2;

            // Options
            var optionssize = (Flags & PacketFlags.FROM_INCLUDED) != 0
                ? From.Size : 0;

            optionssize += (Flags & PacketFlags.SIGNATURE_INCLUDED) != 0
                ? From.SigningPublicKey.Certificate.SignatureLength
                : 0;

            optionssize += (Flags & PacketFlags.MAX_PACKET_SIZE_INCLUDED) != 0
                ? 2 : 0;

            optionssize += (Flags & PacketFlags.DELAY_REQUESTED) != 0
                ? 2 : 0;

            var header = new BufLen(new byte[headersize + optionssize]);
            var writer = new BufRefLen(header);

            writer.WriteFlip32(SendStreamId);
            writer.WriteFlip32(ReceiveStreamId);
            writer.WriteFlip32(SequenceNumber);
            writer.WriteFlip32(AckTrhough);

            writer.Write8((byte)NACKs.Count);
            foreach (var nak in NACKs)
            {
                writer.WriteFlip32(nak);
            }

            writer.Write8(ResendDelay);

            writer.WriteFlip16((ushort)Flags);
            writer.WriteFlip16((ushort)optionssize);

            // Options order
            // DELAY_REQUESTED
            // FROM_INCLUDED
            if ((Flags & PacketFlags.FROM_INCLUDED) != 0)
            {
                writer.Write(From.ToByteArray());
            }
            // MAX_PACKET_SIZE_INCLUDED
            if ((Flags & PacketFlags.MAX_PACKET_SIZE_INCLUDED) != 0)
            {
                writer.WriteFlip16(MTU);
            }
            // OFFLINE_SIGNATURE
            // SIGNATURE_INCLUDED
            if ((Flags & PacketFlags.SIGNATURE_INCLUDED) != 0)
            {
                writer.Write(I2PSignature.DoSign(SigningKey, header));
            }

#if DEBUG
            if (writer.Length != 0)
            {
                throw new InvalidOperationException("StreamingPacket Write buffer size error");
            }
#endif

            dest.Write((BufRefLen)header);
            dest.Write((BufRefLen)Payload);
        }