Beispiel #1
0
        protected MACHealth VerifyMAC(SSUHeader header, BufLen key)
        {
            var macdata = new BufLen[] {
                header.MACDataBuf,
                header.IV,
                BufUtils.Flip16BL((ushort)((ushort)header.MACDataBuf.Length ^ I2PConstants.SSU_PROTOCOL_VERSION))
            };
            var recvhash = I2PHMACMD5Digest.Generate(macdata, key, MACBuf);
            var ok       = header.MAC.Equals(recvhash);

            if (ok)
            {
                IntroMACsReceived = 0;
            }
            else
            {
                DebugUtils.LogDebug(() => string.Format("SSU {0}: {1} Current MAC check fail. Payload {2} bytes. ",
                                                        this, Session.DebugId, header.MACDataBuf.Length));

                if ((int)DebugUtils.LogLevel <= (int)DebugUtils.LogLevels.Debug)
                {
                    if (Session.IntroKey != null)
                    {
                        var recvhashi = I2PHMACMD5Digest.Generate(macdata, new BufLen(Session.IntroKey), MACBuf);
                        var oki       = header.MAC.Equals(recvhashi);
                        DebugUtils.Log("SSU " + this.ToString() + ": " + Session.DebugId + ". " +
                                       "Session Intro key match: " + oki.ToString());
                    }
                }

                var recvhash2 = I2PHMACMD5Digest.Generate(macdata, new BufLen(Session.MyRouterContext.IntroKey), MACBuf);
                var ok2       = header.MAC.Equals(recvhash2);
                DebugUtils.LogDebug(() => string.Format("SSU {0}: {1} My intro MAC key match: {3}. Payload {2} bytes. ",
                                                        this, Session.DebugId, header.MACDataBuf.Length, ok2));

                if (ok2)
                {
                    if (++IntroMACsReceived > 5)
                    {
                        var reason = string.Format("SSU {0}: {1}. {2} intro key matches in a row. The other side seems to have started a new session.",
                                                   this, Session.DebugId, IntroMACsReceived);

                        DebugUtils.Log(reason);
                        return(MACHealth.AbandonSession);
                    }

                    return(MACHealth.UseOurIntroKey);
                }
            }

            return(ok ? MACHealth.Match : MACHealth.Missmatch);
        }
Beispiel #2
0
        protected MACHealth VerifyMAC(SSUHeader header, BufLen key)
        {
            var macdata = new BufLen[] {
                header.MACDataBuf,
                header.IV,
                BufUtils.Flip16BL((ushort)((ushort)header.MACDataBuf.Length ^ I2PConstants.SSU_PROTOCOL_VERSION))
            };

            var recvhash = I2PHMACMD5Digest.Generate(macdata, key, MACBuf);
            var ok       = header.MAC.Equals(recvhash);
            var result   = ok ? MACHealth.Match : MACHealth.Missmatch;

            if (!ok)
            {
                if (++ConsecutiveMACCheckFailures > 3)
                {
                    result = MACHealth.AbandonSession;
                }
            }
            else
            {
                ConsecutiveMACCheckFailures = 0;
            }

#if DEBUG
            if (result != MACHealth.Match)
            {
                Logging.LogTransport($"SSU {this}: VerifyMAC {result} [{ConsecutiveMACCheckFailures}] {key}");
            }
            else
            {
                Logging.LogDebugData($"SSU {this}: VerifyMAC {result} [{ConsecutiveMACCheckFailures}] {key}");
            }
#endif

#if DEBUG && SSU_TRACK_OLD_MAC_KEYS
            if (result != MACHealth.Match)
            {
                result = CheckOldKeys(header, macdata, MACBuf, result);
            }
#endif
            return(result);
        }
Beispiel #3
0
        private MACHealth CheckOldKeys(
            SSUHeader header,
            BufLen[] macdata,
            BufLen mACBuf,
            MACHealth result)
        {
            if (!SSUSession.OldKeys.TryGetValue(Session.RemoteEP, out var oldkeys))
            {
                return(result);
            }

            foreach (var keyinfo in oldkeys.ToArray())
            {
                var recvhashi = I2PHMACMD5Digest.Generate(macdata, keyinfo.Key, MACBuf);
                var oki       = header.MAC.Equals(recvhashi);

                Logging.LogTransport($"SSU {this}: " +
                                     $"Old key from {keyinfo.Created} {keyinfo.CreatedDelta, -20} {keyinfo.Type, -10} match: {oki, -6} {keyinfo.Key}");
            }

            return(result);
        }
Beispiel #4
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);
        }