Exemplo n.º 1
0
        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());
        }
Exemplo n.º 2
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);

            var usekey = CurrentPayloadKey;

            switch (macstate)
            {
            case MACHealth.AbandonSession: return(null);

            case MACHealth.Missmatch: return(this);

            case MACHealth.UseOurIntroKey:
                usekey = Session.MyRouterContext.IntroKey;
                break;
            }

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

            header.SkipExtendedHeaders(reader);

            return(HandleMessage(header, reader));
        }
Exemplo n.º 3
0
 internal void ReportRelayResponse(SSUHeader header, RelayResponse response, IPEndPoint ep)
 {
     if (RelayResponseReceived != null)
     {
         lock ( RelayResponseReceivedLock )
         {
             RelayResponseReceived(header, response, ep);
         }
     }
 }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
        public override SSUState HandleMessage(SSUHeader header, BufRefLen reader)
        {
#if LOG_ALL_TRANSPORT
            Logging.LogTransport($"SSU RelayRequestState: {Session.DebugId} Received {header.MessageType}");
#endif

            if (header.MessageType == SSUHeader.MessageTypes.RelayResponse)
            {
                var response = new RelayResponse(reader);
                return(HandleRelayResponse(response));
            }

            return(this);
        }
Exemplo n.º 6
0
        public override SSUState HandleMessage(SSUHeader header, BufRefLen reader)
        {
            switch (header.MessageType)
            {
            case SSUHeader.MessageTypes.SessionRequest:
                var req = new SessionRequest(reader, I2PPublicKey.DefaultAsymetricKeyCert);
                DebugUtils.Log("SSU SessionCreatedState " + Session.DebugId + " : OK SessionRequest received.");

                BufUtils.DHI2PToSessionAndMAC(out Session.SharedKey, out Session.MACKey,
                                              req.XKey.ModPow(PrivateKey.ToBigInteger(), I2PConstants.ElGamalP));

                Session.Host.ReportedAddress(new IPAddress(req.Address.ToByteArray()));

                // TODO: Remove comment when relaying is implemented

                /*
                 * if ( header.ExtendedOptions != null )
                 * {
                 *  if ( header.ExtendedOptions.Length == 2 && ( ( header.ExtendedOptions[0] & 0x01 ) != 0 ) )
                 *  {
                 *      RelayTag = BufUtils.RandomUint();
                 *  }
                 * }*/

                Request = req;
                SendSessionCreated();

                return(this);

            case SSUHeader.MessageTypes.RelayResponse:
                DebugUtils.LogDebug(() => string.Format("SSU SessionCreatedState {0}: RelayResponse received from {1}.",
                                                        Session.DebugId, (Session.RemoteEP == null ? "<null>" : Session.RemoteEP.ToString())));
                var response = new RelayResponse(reader);
                Session.Host.ReportRelayResponse(header, response, Session.RemoteEP);
                break;

            case SSUHeader.MessageTypes.SessionConfirmed:
                return(ParseSessionConfirmed(header, reader));

            case SSUHeader.MessageTypes.PeerTest:
                HandleIncomingPeerTestPackage(reader);
                break;

            default:
                DebugUtils.Log("SSU SessionCreatedState: Session " + Session.DebugId + " Unexpected Message: " + header.MessageType.ToString());
                break;
            }

            return(this);
        }
Exemplo n.º 7
0
 void Host_RelayResponseReceived(SSUHeader header, RelayResponse response, IPEndPoint ep)
 {
     if (header.MessageType == SSUHeader.MessageTypes.RelayResponse)
     {
         if (ep.Address.Equals(CurrentIntroducer.EndPoint.Address))
         {
             HandleRelayResponse(response);
         }
         else
         {
             Logging.LogTransport(
                 $"SSU RelayRequestState: {Session.DebugId} RelayResponse from {ep.Address} received. Waiting for response from {CurrentIntroducer.EndPoint.Address}.");
         }
     }
 }
Exemplo n.º 8
0
        public override SSUState HandleMessage(SSUHeader header, BufRefLen reader)
        {
            if (header.MessageType == SSUHeader.MessageTypes.SessionCreated)
            {
#if LOG_ALL_TRANSPORT
                Logging.LogTransport("SSU SessionConfirmedState " + Session.DebugId + ": Unexpected message received: " + header.MessageType.ToString());
#endif
                return(this);
            }

            Logging.LogTransport("SSU SessionConfirmedState: Session " + Session.DebugId + " established. " +
                                 header.MessageType.ToString() + " received. Moving to Established state.");
            var next = new EstablishedState(Session);
            Session.ReportConnectionEstablished();

            return(next.HandleMessage(header, reader));
        }
Exemplo n.º 9
0
        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));
        }
Exemplo n.º 10
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));
        }
Exemplo n.º 11
0
 // MAC verified and packet dectrypted
 public abstract SSUState HandleMessage(SSUHeader header, BufRefLen reader);
Exemplo n.º 12
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.Random(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_ALL_TRANSPORT
            DebugUtils.Log(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();
            Session.Host.Send(dest, data);
        }
Exemplo n.º 13
0
        public override SSUState HandleMessage(SSUHeader header, BufRefLen reader)
        {
            DataSent();
#if LOG_ALL_TRANSPORT
            DebugUtils.Log("SSU EstablishedState +" + Session.TransportInstance.ToString() + "+ received: " +
                           header.MessageType.ToString() + ": " + SSUHost.SSUDateTime(header.TimeStamp).ToString());
#endif
            switch (header.MessageType)
            {
            case SSUHeader.MessageTypes.Data:
                try
                {
                    var datamsg = new SSUDataMessage(reader, Session.Defragmenter);
                    if (datamsg.ExplicitAcks != null)
                    {
                        Session.Fragmenter.GotAck(datamsg.ExplicitAcks);
                    }
                    if (datamsg.AckBitfields != null)
                    {
                        Session.Fragmenter.GotAck(datamsg.AckBitfields);
                    }
                    if (datamsg.NewMessages != null)
                    {
                        foreach (var msg in datamsg.NewMessages)
                        {
                            var i2npmsg = I2NPMessage.ReadHeader5((BufRefLen)msg.GetPayload());

#if LOG_ALL_TRANSPORT
                            DebugUtils.Log("SSU EstablishedState +" + Session.TransportInstance.ToString() + "+ complete message " +
                                           msg.MessageId.ToString() + ": " + i2npmsg.Expiration.ToString());
#endif

                            if (i2npmsg.MessageType == I2PCore.Tunnel.I2NP.Messages.I2NPMessage.MessageTypes.DeliveryStatus)
                            {
                                if (((DeliveryStatusMessage)i2npmsg.Message).IsNetworkId((ulong)I2PConstants.I2P_NETWORK_ID))
                                {
                                    continue;
                                }
                            }

                            Session.MessageReceived(i2npmsg);
                        }
                    }
                }
                catch (Exception ex)
                {
                    DebugUtils.Log("EstablishedState: SSUHost.SSUMessageTypes.Data", ex);
                }
                break;

            case SSUHeader.MessageTypes.SessionDestroyed:
                DebugUtils.LogDebug(() => string.Format("SSU EstablishedState {0}: SessionDestroyed received.", Session.DebugId));
                SendSessionDestroyed();
                return(null);

            case SSUHeader.MessageTypes.PeerTest:
                HandleIncomingPeerTestPackage(reader);
                break;

            case SSUHeader.MessageTypes.RelayResponse:
                DebugUtils.LogDebug(() => string.Format("SSU EstablishedState {0}: RelayResponse received from {1}.",
                                                        Session.DebugId, Session.RemoteEP));
                var response = new RelayResponse(reader);
                Session.Host.ReportRelayResponse(header, response, Session.RemoteEP);
                break;

            case SSUHeader.MessageTypes.RelayIntro:
                var intro = new RelayIntro(reader);
                DebugUtils.LogDebug(() => $"SSU EstablishedState {Session.DebugId}: RelayIntro received from {Session.RemoteEP} for {intro.AliceEndpoint}.");
                Session.Host.Send(intro.AliceEndpoint, new BufLen(new byte[0]));
                break;

            case SSUHeader.MessageTypes.RelayRequest:
                // if ( !SSUHost.IntroductionSupported ) throw new Exception( "SSU relay introduction not supported" );
                DebugUtils.LogDebug(() => string.Format("SSU EstablishedState {0}: Relay introduction not supported.", Session.DebugId));
                break;

            case SSUHeader.MessageTypes.SessionRequest:
                DebugUtils.LogDebug(() => string.Format("SSU EstablishedState {0}: SessionRequest received. Ending session.", Session.DebugId));
                SendSessionDestroyed();
                return(null);

            default:
                DebugUtils.LogDebug(() => string.Format("SSU EstablishedState {0}: Unexpected message received: {1}.",
                                                        Session.DebugId, header.MessageType));
                break;
            }

            return(this);
        }