Ejemplo n.º 1
0
        void UpdateCachedFields(BufRef reader)
        {
            CachedKey        = new I2PIdentHash(reader);
            CachedFrom       = new I2PIdentHash(reader);
            CachedLookupType = (LookupTypes)reader.Read8();
            if (((byte)CachedLookupType & 0x01) != 0)
            {
                CachedTunnelId = new I2PTunnelId(reader);
            }

            var excludecount = reader.ReadFlip16();

            for (int i = 0; i < excludecount; ++i)
            {
                CachedExcludeList.Add(new DatabaseSearchReplyMessage(reader));
            }

            if (((byte)CachedLookupType & 0x02) != 0)
            {
                CachedReplyKey = new I2PSessionKey(reader);

                var tagcount = reader.Read8();
                CachedTags.Add(new I2PSessionTag(reader));
            }
        }
Ejemplo n.º 2
0
        public static GarlicMessage AESEncryptGarlic(
            Garlic msg,
            I2PSessionKey sessionkey,
            I2PSessionTag tag,
            List <I2PSessionTag> newtags)
        {
            var cipher = new CbcBlockCipher(new AesEngine());

            var payload = msg.ToByteArray();
            var dest    = new BufLen(new byte[65536]);
            // Reserve header + 4 bytes for GarlicMessageLength
            var writer = new BufRefLen(dest, I2NPMaxHeaderSize + 4);

            // Tag as header
            writer.Write(tag.Value);

            // AES block
            var aesstart = new BufLen(writer);
            var aesblock = new GarlicAESBlock(writer, newtags, null, new BufRefLen(payload));

            var pivh = I2PHashSHA256.GetHash(tag.Value);

            cipher.Init(true, sessionkey.Key.ToParametersWithIV(new BufLen(pivh, 0, 16)));
            cipher.ProcessBytes(aesblock.DataBuf);

            var length = writer - dest;

            dest.PokeFlip32((uint)(length - 4), I2NPMaxHeaderSize);

            return(new GarlicMessage(new BufRefLen(dest, I2NPMaxHeaderSize, length)));
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
 public GarlicCloveDeliveryLocal(BufRef reader, byte flag) : base(DeliveryMethod.Local)
 {
     Flag = flag;
     if ((Flag & (byte)DeliveryFlags.Encrypted) != 0)
     {
         SessionKey = new I2PSessionKey(reader);
     }
     if ((Flag & (byte)DeliveryFlags.Delay) != 0)
     {
         Delay = reader.ReadFlip32();
     }
 }
Ejemplo n.º 5
0
 public GarlicCloveDeliveryRouter(BufRef reader, byte flag) : base(DeliveryMethod.Router)
 {
     Flag = flag;
     if ((Flag & (byte)DeliveryFlags.Encrypted) != 0)
     {
         SessionKey = new I2PSessionKey(reader);
     }
     Destination = new I2PIdentHash(reader);
     if ((Flag & (byte)DeliveryFlags.Delay) != 0)
     {
         Delay = reader.ReadFlip32();
     }
 }
Ejemplo n.º 6
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);
        }
Ejemplo n.º 7
0
        public void TestEncodeDecodeAES()
        {
            var m1 = new DeliveryStatusMessage(0x4321);
            var m2 = new DeliveryStatusMessage(0xa3c2);

            var garlic = new Garlic(
                new GarlicClove(
                    new GarlicCloveDeliveryDestination(
                        m1,
                        Destination.IdentHash)),
                new GarlicClove(
                    new GarlicCloveDeliveryDestination(
                        m2,
                        Destination.IdentHash))
                );

            // No tags

            var sessionkey = new I2PSessionKey();
            var sessiontag = new I2PSessionTag();

            var cg     = Garlic.AESEncryptGarlic(garlic, sessionkey, sessiontag, null);
            var egdata = I2NPMessage.Clone(cg);

            var(aesblock, sk) = Garlic.RetrieveAESBlock(egdata, Private, (t) => sessionkey);
            var g2 = new Garlic((BufRefLen)aesblock.Payload);

            Assert.IsTrue(BufUtils.Equal(garlic.ToByteArray(), g2.ToByteArray()));

            // With tags
            var tags = new List <I2PSessionTag>();

            for (int i = 0; i < 30; ++i)
            {
                tags.Add(new I2PSessionTag());
            }

            cg     = Garlic.AESEncryptGarlic(garlic, sessionkey, sessiontag, null);
            egdata = I2NPMessage.Clone(cg);

            (aesblock, sk) = Garlic.RetrieveAESBlock(egdata, Private, (t) => sessionkey);
            g2             = new Garlic((BufRefLen)aesblock.Payload);

            Assert.IsTrue(BufUtils.Equal(garlic.ToByteArray(), g2.ToByteArray()));
        }
Ejemplo n.º 8
0
        public static GarlicMessage EGEncryptGarlic(
            Garlic msg,
            I2PPublicKey pubkey,
            I2PSessionKey sessionkey,
            List <I2PSessionTag> newtags)
        {
            var cipher = new CbcBlockCipher(new AesEngine());

            var payload = msg.ToByteArray();
            var dest    = new BufLen(new byte[65536]);
            // Reserve header + 4 bytes for GarlicMessageLength
            var writer = new BufRefLen(dest, I2NPMaxHeaderSize + 4);

            // ElGamal block
            var egbuf         = new BufLen(new byte[222]);
            var sessionkeybuf = new BufLen(egbuf, 0, 32);
            var preivbuf      = new BufLen(egbuf, 32, 32);
            var egpadding     = new BufLen(egbuf, 64, 158);

            egpadding.Randomize();
            preivbuf.Randomize();
            sessionkeybuf.Poke(sessionkey.Key, 0);

            var iv = new BufLen(I2PHashSHA256.GetHash(preivbuf), 0, 16);

            ElGamalCrypto.Encrypt(writer, egbuf, pubkey, true);

            // AES block
            var aesstart = new BufLen(writer);
            var aesblock = new GarlicAESBlock(writer, newtags, null, new BufRefLen(payload));

            cipher.Init(true, sessionkey.Key.ToParametersWithIV(iv));
            cipher.ProcessBytes(aesblock.DataBuf);

            var length = writer - dest;

            dest.PokeFlip32((uint)(length - 4), I2NPMaxHeaderSize);

            return(new GarlicMessage(new BufRefLen(dest, I2NPMaxHeaderSize, length)));
        }
Ejemplo n.º 9
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 = new I2PSessionKey(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));

            DataBuf = new BufLen(start, 0, reader - start);
        }
Ejemplo n.º 10
0
 public void Reset()
 {
     SessionKey = new I2PSessionKey();
     lock (SessionTags) SessionTags.Clear();
 }
Ejemplo n.º 11
0
        public Garlic DecryptMessage(EGGarlic message)
        {
            lock ( SessionTags )
            {
                var old = SessionTags.Where(p => p.Key.Created.DeltaToNow.ToMinutes > (I2PSessionTag.TagLifetimeMinutes + 2)).ToArray();
                foreach (var one in old)
                {
                    SessionTags.Remove(one.Key);
                }
            }

            var egdata = message.EGData;
            var tag    = new I2PSessionTag(new BufRefLen(egdata, 0, 32));

            I2PSessionKey sessionkey;
            bool          found;

            lock ( SessionTags )
            {
                found = SessionTags.TryGetValue(tag, out sessionkey);
            }

            BufLen aesbuf;

            if (found)
            {
                aesbuf = new BufLen(egdata, 32);

                lock ( SessionTags )
                {
                    SessionTags.Remove(tag);
                }

#if LOG_ALL_TUNNEL_TRANSFER
                DebugUtils.LogDebug("ReceivedSessions: Working tag found for EGarlic.");
#endif

                var pivh = I2PHashSHA256.GetHash(tag.Value);

                Cipher.Init(false, sessionkey.Key.ToParametersWithIV(new BufLen(pivh, 0, 16)));
                Cipher.ProcessBytes(aesbuf);
            }
            else
            {
                BufLen egheader;
                try
                {
                    var egbuf = new BufLen(egdata, 0, 514);
                    egheader = ElGamalCrypto.Decrypt(egbuf, Key, true);
                }
                catch (Exception ex)
                {
                    DebugUtils.Log("ReceivedSessions", ex);
                    return(null);
                }

#if LOG_ALL_TUNNEL_TRANSFER
                DebugUtils.LogDebug("ReceivedSessions: Using ElGamal to decrypt.");
#endif

                sessionkey = new I2PSessionKey(new BufLen(egheader, 0, 32));
                var preiv     = new BufLen(egheader, 32, 32);
                var egpadding = new BufLen(egheader, 64);
                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;

            try
            {
                aesblock = new GarlicAESBlock(new BufRefLen(aesbuf));
            }
            catch (Exception ex)
            {
                DebugUtils.Log("ReceivedSessions", ex);
                return(null);
            }

            if (!aesblock.VerifyPayloadHash())
            {
                DebugUtils.LogDebug("ReceivedSessions: DecryptMessage: AES block SHA256 check failed.");
                return(null);
            }

#if LOG_ALL_TUNNEL_TRANSFER
            DebugUtils.LogDebug("ReceivedSessions: Working Aes block received. " + SessionTags.Count.ToString() + " tags available.");
#endif

            if (aesblock.Tags.Count > 0)
            {
#if LOG_ALL_TUNNEL_TRANSFER
                DebugUtils.LogDebug("ReceivedSessions: " + aesblock.Tags.Count.ToString() + " new tags received.");
#endif
                lock ( SessionTags )
                {
                    foreach (var onetag in aesblock.Tags.ToArray())
                    {
                        SessionTags[new I2PSessionTag(new BufRef(onetag))] = sessionkey;
                    }
                }
            }

            return(new Garlic((BufRefLen)aesblock.Payload));
        }