Beispiel #1
0
        public static (GarlicAESBlock, I2PSessionKey) EGDecryptGarlic(
            GarlicMessage garlic,
            I2PPrivateKey privkey)
        {
            var cipher = new CbcBlockCipher(new AesEngine());
            var egdata = garlic.EGData;

            var egbuf    = new BufLen(egdata, 0, 514);
            var egheader = ElGamalCrypto.Decrypt(egbuf, privkey, true);

            var sessionkey = new I2PSessionKey(new BufLen(egheader, 0, 32));
            var preiv      = new BufLen(egheader, 32, 32);
            var egpadding  = new BufLen(egheader, 64, 158);
            var aesbuf     = new BufLen(egdata, 514);

            var pivh = I2PHashSHA256.GetHash(preiv);

            cipher.Init(false, sessionkey.Key.ToParametersWithIV(new BufLen(pivh, 0, 16)));
            cipher.ProcessBytes(aesbuf);

            GarlicAESBlock aesblock =
                new GarlicAESBlock(new BufRefLen(aesbuf));

            if (!aesblock.VerifyPayloadHash())
            {
                throw new ChecksumFailureException("AES block hash check failed!");
            }

            return(aesblock, sessionkey);
        }
        internal void Run()
        {
            Resend.Do(() =>
            {
                try
                {
                    List <KeyValuePair <II2NPHeader16, GarlicCreationInfo> > tosend = new List <KeyValuePair <II2NPHeader16, GarlicCreationInfo> >();
                    lock ( Window )
                    {
                        var resend = Window.Where(gci => gci.Value.LastSend.DeltaToNow > GarlicTimeBetweenResends);

                        if (WaitingForEGAck != null && WaitingForEGAck.DeltaToNow > GarlicTimeBetweenResends)
                        {
                            DebugUtils.LogDebug("TagsTransferWindow: Run: ElGamal message needs to be resent. Starting over.");
                            Session.Reset();
                        }

                        foreach (var one in resend.ToArray())
                        {
                            var egmsg = Session.Encrypt(true, one.Value.TrackingId, one.Value.Cloves);
                            var npmsg = new GarlicMessage(egmsg.Garlic).GetHeader16(I2NPHeader.GenerateMessageId());
                            one.Value.LastSend.SetNow();
                            tosend.Add(new KeyValuePair <II2NPHeader16, GarlicCreationInfo>(npmsg, egmsg));

                            if (WaitingForEGAck == null && !one.Value.AckMessageId.HasValue)
                            {
                                // Non explicit ack cloves that should not be retransmitted any more.
                                Window.Remove(one.Key);
                            }
                        }
                    }

                    foreach (var pair in tosend)
                    {
                        DebugUtils.LogDebug(string.Format("TagsTransferWindow: Resend: ({0}) TrackingId: {1}, Ack MessageId: {2}.",
                                                          pair.Value.KeyType, pair.Value.TrackingId, pair.Value.AckMessageId));

                        if (pair.Value.AckMessageId.HasValue)
                        {
                            lock ( OutstandingMessageIds )
                            {
                                OutstandingMessageIds[pair.Value.AckMessageId.Value] = pair.Value;
                            }
                        }

                        TunnelSelector(Session.LatestRemoteLeaseSet, pair.Key, pair.Value);
                    }
                }
                catch (Exception ex)
                {
                    Session.Reset();
                    DebugUtils.Log("TagsTransferWindow Run", ex);
                }
            });
        }
Beispiel #3
0
        private static void HandleGarlic(GarlicMessage garlicmsg)
        {
            try
            {
                // No sessions, just accept EG
                var(aesblock, sessionkey) = Garlic.EGDecryptGarlic(
                    garlicmsg,
                    RouterContext.Inst.PrivateKey);

                if (aesblock == null)
                {
                    Logging.LogWarning($"Router: HandleGarlic: Failed to decrypt.");
                    return;
                }

                var garlic = new Garlic((BufRefLen)aesblock.Payload);

#if LOG_ALL_LEASE_MGMT
                Logging.LogDebug($"Router: HandleGarlic: {garlic}");
#endif

                foreach (var clove in garlic.Cloves)
                {
                    try
                    {
                        // Only accept Local to not turn into a bot net.
                        switch (clove.Delivery.Delivery)
                        {
                        case GarlicCloveDelivery.DeliveryMethod.Local:
#if LOG_ALL_LEASE_MGMT
                            Logging.LogDebug(
                                $"Router: HandleGarlic: Delivered Local: {clove.Message}");
#endif
                            TunnelProvider.Inst.DistributeIncomingMessage(null, clove.Message.CreateHeader16);
                            break;

                        default:
                            Logging.LogDebug($"Router HandleGarlic: Dropped clove ({clove})");
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Logging.Log("Router: HandleGarlic switch", ex);
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.Log("Router: HandleGarlic", ex);
            }
        }
        // Returns a tracking id supplied with events
        internal GarlicCreationInfo Send(bool explack, params GarlicCloveDelivery[] cloves)
        {
            GarlicCreationInfo egmsg = null;

            try
            {
                egmsg = Session.Encrypt(explack, I2NPHeader.GenerateMessageId(), cloves);
                var npmsg = new GarlicMessage(egmsg.Garlic).GetHeader16(I2NPHeader.GenerateMessageId());

                if (explack || WaitingForEGAck != null || egmsg.KeyType == GarlicCreationInfo.KeyUsed.ElGamal)
                {
                    if (egmsg.KeyType == GarlicCreationInfo.KeyUsed.ElGamal)
                    {
                        LatestEGMessage = egmsg;
                        WaitingForEGAck = TickCounter.Now;
                    }

                    egmsg.LastSend = TickCounter.Now;
                    lock ( Window )
                    {
                        Window[egmsg.TrackingId] = egmsg;
                    }
                }

                if (egmsg.AckMessageId.HasValue)
                {
                    lock ( OutstandingMessageIds )
                    {
                        OutstandingMessageIds[egmsg.AckMessageId.Value] = egmsg;
                    }
                }

                DebugUtils.LogDebug(string.Format("TagsTransferWindow: Send: ({0}) TrackingId: {1}, Ack MessageId: {2}.",
                                                  egmsg.KeyType, egmsg.TrackingId, egmsg.AckMessageId));

                TunnelSelector(Session.LatestRemoteLeaseSet, npmsg, egmsg);
            }
            catch (Exception ex)
            {
                Session.Reset();
                DebugUtils.Log("TagsTransferWindow Send", ex);
            }

            return(egmsg);
        }
Beispiel #5
0
        public Garlic DecryptMessage(GarlicMessage message)
        {
            var egdata = message.EGData;

            var(aesblock, sessionkey) = Garlic.RetrieveAESBlock(
                message,
                PrivateKey,
                (stag) =>
            {
                return(SessionTags.TryRemove(stag, out var sessionkeyfound) ? sessionkeyfound : null);
            });

            if (aesblock is null)
            {
                Logging.LogDebug($"{Owner} ReceivedSessions: Aes block decrypt failed.");
                return(null);
            }

#if LOG_ALL_LEASE_MGMT
            Logging.LogDebug($"{Owner} ReceivedSessions: Working Aes block received. {SessionTags.Count()} tags available.");
#endif

            if (sessionkey != null && aesblock.Tags.Count > 0)
            {
#if LOG_ALL_LEASE_MGMT
                Logging.LogDebug($"{Owner} ReceivedSessions: {aesblock.Tags.Count} new tags received.");
#endif
                foreach (var onetag in aesblock.Tags)
                {
                    SessionTags[new I2PSessionTag(new BufRef(onetag))] =
                        sessionkey;
                }
            }

            return(new Garlic((BufRefLen)aesblock.Payload));
        }
Beispiel #6
0
        void InboundTunnel_GarlicMessageReceived(GarlicMessage msg)
        {
            try
            {
                var decr = IncommingSessions.DecryptMessage(msg.Garlic);
                if (decr == null)
                {
                    return;
                }

#if LOG_ALL_TUNNEL_TRANSFER
                DebugUtils.LogDebug("ClientDestination: GarlicMessageReceived: " + decr.ToString());
#endif

                foreach (var clove in decr.Cloves)
                {
                    try
                    {
                        switch (clove.Delivery.Delivery)
                        {
                        case GarlicCloveDelivery.DeliveryMethod.Local:
#if LOG_ALL_TUNNEL_TRANSFER
                            DebugUtils.LogDebug(() => string.Format(
                                                    "ClientDestination: GarlicMessageReceived: Delivered Local: {0}", clove.Message));
#endif
                            TunnelProvider.Inst.DistributeIncomingMessage(null, clove.Message.Header16);
                            break;

                        case GarlicCloveDelivery.DeliveryMethod.Router:
                            var dest = ((GarlicCloveDeliveryRouter)clove.Delivery).Destination;
#if LOG_ALL_TUNNEL_TRANSFER
                            DebugUtils.LogDebug(() => string.Format(
                                                    "ClientDestination: GarlicMessageReceived: Delivered Router: {0} {1}",
                                                    dest.Id32Short, clove.Message));
#endif
                            TransportProvider.Send(dest, clove.Message);
                            break;

                        case GarlicCloveDelivery.DeliveryMethod.Tunnel:
                            var tone = (GarlicCloveDeliveryTunnel)clove.Delivery;
#if LOG_ALL_TUNNEL_TRANSFER
                            DebugUtils.LogDebug(() => string.Format(
                                                    "ClientDestination: GarlicMessageReceived: Delivered Tunnel: {0} TunnelId: {1} {2}",
                                                    tone.Destination.Id32Short, tone.Tunnel, clove.Message));
#endif
                            TransportProvider.Send(tone.Destination, new TunnelGatewayMessage(clove.Message.Header16, tone.Tunnel));
                            break;

                        case GarlicCloveDelivery.DeliveryMethod.Destination:
#if LOG_ALL_TUNNEL_TRANSFER
                            DebugUtils.LogDebug(() => string.Format(
                                                    "ClientDestination: GarlicMessageReceived: Delivered Destination: {0}", clove.Message));
#endif
                            DestinationMessageReceived(clove.Message);
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        DebugUtils.Log("ClientDestination GarlicDecrypt Clove", ex);
                    }
                }
            }
            catch (Exception ex)
            {
                DebugUtils.Log("ClientDestination GarlicDecrypt", ex);
            }
        }
Beispiel #7
0
 void tunnel_GarlicMessageReceived(GarlicMessage msg)
 {
 }
Beispiel #8
0
        public static (GarlicAESBlock, I2PSessionKey) RetrieveAESBlock(
            GarlicMessage garlic,
            I2PPrivateKey privatekey,
            Func <I2PSessionTag, I2PSessionKey> findsessionkey)
        {
            GarlicAESBlock result;

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

            var tag        = new I2PSessionTag(new BufRefLen(garlic.EGData, 0, 32));
            var sessionkey = findsessionkey?.Invoke(tag);

#if LOG_ALL_LEASE_MGMT
            Logging.LogDebug($"Garlic: Session key found {sessionkey}");
#endif
            if (sessionkey != null)
            {
                var aesbuf = new BufLen(garlic.EGData, 32);
                var pivh   = I2PHashSHA256.GetHash(tag.Value);

                cipher.Init(false, sessionkey.Key.ToParametersWithIV(new BufLen(pivh, 0, 16)));
                cipher.ProcessBytes(aesbuf);

                try
                {
                    result = new GarlicAESBlock(new BufRefLen(aesbuf));

                    if (!result.VerifyPayloadHash())
                    {
                        Logging.LogDebug("Garlic: DecryptMessage: AES block SHA256 check failed.");
                        return(null, null);
                    }

                    return(result, sessionkey);
                }
                catch (ArgumentException ex)
                {
                    Logging.Log("Garlic", ex);
                }
                catch (Exception ex)
                {
                    Logging.Log("Garlic", ex);
                    return(null, null);
                }
            }

#if LOG_ALL_LEASE_MGMT
            Logging.LogDebug("Garlic: No session key. Using ElGamal to decrypt.");
#endif

            try
            {
                (result, sessionkey) = Garlic.EGDecryptGarlic(garlic, privatekey);
#if LOG_ALL_LEASE_MGMT
                Logging.LogDebug($"Garlic: EG session key {sessionkey}");
#endif
            }
            catch (Exception ex)
            {
                Logging.LogDebug("Garlic: ElGamal DecryptMessage failed");
                Logging.LogDebugData($"ReceivedSessions {ex}");
                return(null, null);
            }

            return(result, sessionkey);
        }
Beispiel #9
0
 void GarlicMessageReceived(GarlicMessage msg)
 {
 }
Beispiel #10
0
        public static I2NPMessage GetMessage(
            I2NPMessage.MessageTypes messagetype,
            BufRef reader,
            uint?msgid = null)
        {
            I2NPMessage result = null;

            try
            {
                switch (messagetype)
                {
                case I2NPMessage.MessageTypes.Garlic:
                    result = new GarlicMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.Data:
                    result = new DataMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.DatabaseSearchReply:
                    result = new DatabaseSearchReplyMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.DatabaseStore:
                    result = new DatabaseStoreMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.DeliveryStatus:
                    result = new DeliveryStatusMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.TunnelData:
                    result = new TunnelDataMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.TunnelGateway:
                    result = new TunnelGatewayMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.DatabaseLookup:
                    result = new DatabaseLookupMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.VariableTunnelBuild:
                    result = new VariableTunnelBuildMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.TunnelBuild:
                    result = new TunnelBuildMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.TunnelBuildReply:
                    result = new TunnelBuildReplyMessage(reader);
                    break;

                case I2NPMessage.MessageTypes.VariableTunnelBuildReply:
                    result = new VariableTunnelBuildReplyMessage(reader);
                    break;

                default:
                    Logging.LogDebug($"GetMessage: '{messagetype}' is not a known message type!");
                    throw new NotImplementedException();
                }
            }
            catch (Exception ex)
            {
                Logging.Log("GetMessage", ex);
                throw;
            }

            if (result != null && msgid.HasValue)
            {
                result.MessageId = msgid.Value;
            }

            return(result);
        }