Esempio n. 1
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");
            }
        }
Esempio n. 2
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);
        }
Esempio n. 3
0
        public GarlicAESBlock(BufRefLen reader)
        {
            var start = new BufLen(reader);

            TagCount = reader.ReadBufLen(2);
            var tags = TagCount.PeekFlip16(0);

            if (tags > 0)
            {
                if (tags * I2PSessionTag.TagLength > start.Length)
                {
                    throw new ArgumentException("GarlicAESBlock: Not enough data for the tags supplied.");
                }
                for (int i = 0; i < tags; ++i)
                {
                    Tags.Add(reader.ReadBufLen(I2PSessionTag.TagLength));
                }
            }
            PayloadSize = reader.ReadBufLen(4);
            PayloadHash = reader.ReadBufLen(32);
            Flag        = reader.ReadBufLen(1);
            if (Flag[0] != 0)
            {
                NewSessionKey = reader.ReadBufLen(32);
            }
            var pllen = PayloadSize.PeekFlip32(0);

            if (pllen > reader.Length)
            {
                throw new ArgumentException("GarlicAESBlock: Not enough data payload supplied.");
            }
            Payload = reader.ReadBufLen((int)pllen);
            Padding = reader.ReadBufLen(BufUtils.Get16BytePadding(reader - start));
        }
Esempio n. 4
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);
        }
Esempio n. 5
0
        public BufLen GenerateData(I2NPMessage msg)
        {
            if (NTCPContext == null)
            {
                throw new Exception("NTCP Session not negotiated!");
            }
            if (NTCPContext.Encryptor == null)
            {
                throw new Exception("NTCP encryptor not available");
            }

            var data = msg != null ? msg.Header16.HeaderAndPayload: null;

            var datalength = msg == null ? 4 : data.Length;
            var buflen     = 2 + datalength + 4;
            var padlength  = BufUtils.Get16BytePadding(buflen);

            buflen += padlength;

            var buf    = new BufLen(new byte[buflen]);
            var writer = new BufRefLen(buf);

            // Length
            if (msg == null)
            {
                // Send timestamp
                writer.Write16(0);
                writer.WriteFlip32((uint)(DateTime.UtcNow - I2PDate.RefDate).TotalSeconds);
            }
            else
            {
                if (data.Length > 16378)
                {
                    throw new ArgumentException("NTCP data can be max 16378 bytes long!");
                }
                writer.WriteFlip16((ushort)data.Length);
                writer.Write(data);
            }

            // Pad
            writer.Write(BufUtils.Random(writer.Length - 4));

            // Checksum
            var checkbuf = new BufLen(buf, 0, writer - buf);
            var checksum = LZUtils.Adler32(1, checkbuf);

            writer.WriteFlip32(checksum);

            // Encrypt
            NTCPContext.Encryptor.ProcessBytes(buf);

            return(buf);
        }
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.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);
            });
        }
Esempio n. 7
0
        public GarlicAESBlock(
            BufRefLen reader,
            IList <I2PSessionTag> tags,
            I2PSessionKey newsessionkey,
            BufRefLen payload)
        {
            var start = new BufLen(reader);

            // Allocate
            TagCount = reader.ReadBufLen(2);
            if (tags != null)
            {
                for (int i = 0; i < tags.Count; ++i)
                {
                    Tags.Add(reader.ReadBufLen(I2PSessionTag.TagLength));
                }
            }
            PayloadSize = reader.ReadBufLen(4);
            PayloadHash = reader.ReadBufLen(32);
            Flag        = reader.ReadBufLen(1);
            if (newsessionkey != null)
            {
                reader.ReadBufLen(32);
            }
            var pllen = Math.Min(reader.Length, payload.Length);

            Payload = reader.ReadBufLen(pllen);
            Padding = reader.ReadBufLen(BufUtils.Get16BytePadding(reader - start));

            // Write
            TagCount.PokeFlip16((ushort)(tags == null ? 0 : tags.Count), 0);
            if (tags != null)
            {
                for (int i = 0; i < tags.Count; ++i)
                {
                    Tags[i].Poke(tags[i].Value, 0);
                }
            }
            Flag[0] = (byte)(newsessionkey != null ? 0x01 : 0);
            if (newsessionkey != null)
            {
                NewSessionKey.Poke(newsessionkey.Key, 0);
            }
            Payload.Poke(new BufLen(payload, 0, pllen), 0);
            payload.Seek(pllen);
            PayloadSize.PokeFlip32((uint)pllen, 0);
            PayloadHash.Poke(I2PHashSHA256.GetHash(Payload), 0);
            Padding.Randomize();

            DataBuf = new BufLen(start, 0, reader - start);
        }
Esempio n. 8
0
        public SessionCreated(BufRef reader, I2PCertificate cert)
        {
            Certificate = cert;

            Y = reader.ReadBufLen(Certificate.PublicKeyLength);
            var ipsize = reader.Read8();

            Address    = reader.ReadBufLen(ipsize);
            Port       = reader.ReadBufLen(2);
            RelayTag   = reader.ReadBufLen(4);
            SignOnTime = reader.ReadBufLen(4);
            var paddedsignlen = cert.SignatureLength + BufUtils.Get16BytePadding(cert.SignatureLength);

            SignatureEncrBuf = reader.ReadBufLen(paddedsignlen);
            Signature        = new BufLen(SignatureEncrBuf, 0, cert.SignatureLength);
        }
Esempio n. 9
0
        private BufLen ReadBlock()
        {
            var inbufend = 2 + BlockLength + 4;

            inbufend += BufUtils.Get16BytePadding(inbufend);

            while (InBufPos < inbufend)
            {
                if (MySocket.Available > 0)
                {
                    var len = MySocket.Receive(InBuf, InBufPos, inbufend - InBufPos, SocketFlags.None);
                    if (len == 0)
                    {
                        throw new EndOfStreamEncounteredException();
                    }
                    InBufPos += len;
                }
                else
                {
                    Thread.Sleep(400);
                    if (!MySocket.Connected)
                    {
                        throw new EndOfStreamEncounteredException();
                    }
                }
            }

            Cipher.ProcessBytes(new BufLen(InBuf, 16, InBufPos - 16));

            var checksum = LZUtils.Adler32(1, new BufLen(InBuf, 0, InBufPos - 4));
            var blocksum = BufUtils.Flip32(InBuf, InBufPos - 4);

            if (checksum != blocksum)
            {
                throw new ChecksumFailureException("NTCPReader: Received Adler checksum mismatch.");
            }

            var result = new BufLen(InBuf, 2, BlockLength);

            BlockLength = -1;

#if LOG_ALL_TRANSPORT
            Logging.LogTransport(string.Format("NTCPReader +{1}+ block received: {0} bytes [0x{0:X}]", result.Length, Context.TransportInstance));
#endif
            return(result.Clone());
        }
Esempio n. 10
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. 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());
        }
Esempio n. 12
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), (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);
            });
        }
Esempio n. 13
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)
            {
#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);
            });
        }
Esempio n. 14
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");
            }
        }
Esempio n. 15
0
        /**
         * From PacketBuilder.java
         * -----8<-----
         * @param packet prepared packet with the first 32 bytes empty and a length
         *               whose size is mod 16.
         *               As of 0.9.7, length non-mod-16 is allowed; the
         *               last 1-15 bytes are included in the MAC calculation but are not encrypted.
         * -----8<-----
         */

        protected void SendMessage(
            IPEndPoint dest,
            SSUHeader.MessageTypes message,
            BufLen mackey,
            BufLen cryptokey,
            SendMessageGenerator gen,
            SendMessageGenerator genextrapadding)
        {
            var start = Session.Host.SendBuffers.Pop();

            var writer = new BufRefLen(start);
            var header = new SSUHeader(writer, message);

            if (!gen(start, writer))
            {
                return;
            }

            // Do not cut to datalen & ~0xf as that might make data at the end unencrypted
            var datapadding = BufUtils.Get16BytePadding(writer - start);

            writer.Write(BufUtils.RandomBytes(datapadding));
            var datalen = writer - start;

            var encryptedbuf = new BufLen(start, 32, datalen - 32);

            // TODO: Adding extra padding does not seem to work
            if (genextrapadding != null)
            {
                if (!genextrapadding(start, writer))
                {
                    return;
                }
            }

            var packetlen = writer - start;
            var data      = new BufLen(start, 0, packetlen);
            var hmac      = new BufLen(data, 32);

            SendMessageCipher.Init(true, cryptokey.ToParametersWithIV(header.IV));
            SendMessageCipher.ProcessBytes(encryptedbuf);

            I2PHMACMD5Digest.Generate(new BufLen[] {
                hmac,
                header.IV,
                BufUtils.Flip16BL((ushort)((ushort)hmac.Length ^ I2PConstants.SSU_PROTOCOL_VERSION))
            }, mackey, header.MAC);

#if LOG_MUCH_TRANSPORT
            Logging.LogTransport(string.Format("SSUState SendMessage {0}: encrlen {1} bytes [0x{1:X}] (padding {2} bytes [0x{2:X}]), " +
                                               "hmac {3} bytes [0x{3:X}], sendlen {4} bytes [0x{4:X}]",
                                               Session.DebugId,
                                               encryptedbuf.Length,
                                               datapadding,
                                               hmac.Length,
                                               data.Length));
#endif

            DataSent();
            Send(dest, data);
        }
Esempio n. 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);
            });
        }