private static ZipArchive GetRouterInfoFiles(BufLen data) { try { var reader = new BufRefLen(data); var header = new I2PSU3Header(reader); if (header.FileType != I2PSU3Header.SU3FileTypes.Zip) { throw new ArgumentException($"Unknown FileType in SU3: {header.FileType}"); } if (header.ContentType != I2PSU3Header.SU3ContentTypes.SeedData) { throw new ArgumentException($"Unknown ContentType in SU3: {header.ContentType}"); } // TODO: Verify signature var s = new BufRefStream(); s.Write(reader); return(new ZipArchive(s)); } catch (Exception ex) { Logging.Log(ex); } return(null); }
public void TestAESBlock() { for (int runs = 0; runs < 10; ++runs) { var buf = new BufLen(new byte[30000]); var writer = new BufRefLen(buf); var data = BufUtils.RandomBytes(1 + BufUtils.RandomInt(45)); var datar = new BufRefLen(data); var tags = new List <I2PSessionTag>(); for (int i = 0; i < BufUtils.RandomInt(5); ++i) { tags.Add(new I2PSessionTag()); } var newsession = BufUtils.RandomDouble(1.0) < 0.3 ? new I2PSessionKey() : null; var b1 = new GarlicAESBlock(writer, tags, newsession, datar); var bldata = new BufLen(buf, 0, writer - buf).Clone(); var b2 = new GarlicAESBlock(new BufRefLen(bldata)); var b1ar = new BufLen(b1.ToByteArray()); var b2ar = new BufLen(b2.ToByteArray()); Assert.IsTrue(b1ar == b2ar); var bufs = new BufRefStream(); b1.Write(bufs); var b3 = new GarlicAESBlock(new BufRefLen(bufs.ToByteArray())); var b3ar = new BufLen(b3.ToByteArray()); Assert.IsTrue(b1ar == b3ar); } }
internal static byte[] Send(DHHandshakeContext context) { var dest = new byte[288]; var writer = new BufRefLen(dest); var keys = I2PPrivateKey.GetNewKeyPair(); context.PrivateKey = keys.PrivateKey; context.X = keys.PublicKey; context.XBuf = context.X.Key; context.HXxorHI = new BufLen(I2PHashSHA256.GetHash(context.XBuf)); #if LOG_ALL_TRANSPORT Logging.LogTransport( "SessionRequest: Remote cert: " + context.RemoteRI.Certificate.ToString() + ". XBuf len: " + context.XBuf.Length.ToString()); #endif var idenhash = context.RemoteRI.IdentHash; for (int i = 0; i < context.HXxorHI.Length; ++i) { context.HXxorHI[i] ^= idenhash.Hash[i]; } writer.Write(context.XBuf); writer.Write(context.HXxorHI); return(dest); }
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)); }
internal static byte[] Send(DHHandshakeContext context) { var dest = new byte[288]; var writer = new BufRefLen(dest); var keys = I2PPrivateKey.GetNewKeyPair(); context.PrivateKey = keys.PrivateKey; context.X = keys.PublicKey; context.XBuf = context.X.Key; context.HXxorHI = new BufLen(I2PHashSHA256.GetHash(context.XBuf)); Logging.LogDebugData( $"SessionRequest: Remote cert: {context.RemoteRI.Certificate}. XBuf len: {context.XBuf.Length}"); var idenhash = context.RemoteRI.IdentHash; for (int i = 0; i < context.HXxorHI.Length; ++i) { context.HXxorHI[i] ^= idenhash.Hash[i]; } writer.Write(context.XBuf); writer.Write(context.HXxorHI); return(dest); }
public DatabaseStoreMessage( I2PLeaseSet leaseset, uint replytoken, I2PIdentHash replygw, I2PTunnelId replytunnelid) { var ls = leaseset.ToByteArray(); AllocateBuffer(32 + 5 + (replytoken != 0 ? 4 + 32: 0) + ls.Length); var writer = new BufRefLen(Payload); writer.Write(leaseset.Destination.IdentHash.Hash); writer.Write8((byte)MessageContent.LeaseSet); writer.Write32(replytoken); if (replytoken != 0) { writer.Write32(replytunnelid); if (replygw == null || replygw.Hash.Length != 32) { throw new FormatException("ReplyGateway has to be 32 bytes long!"); } writer.Write(replygw.Hash); } writer.Write(ls); UpdateCachedFields((BufRefLen)Payload); }
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)); }
public DataFragment Send(BufRefLen writer) { if (AllFragmentsSent || writer.Length < 10) { return(null); } var fragsize = Math.Min(FragmentReader.Length, writer.Length - 7); // This would be nice, but it would limit the size of I2NP messages. //fragsize = Math.Min( ( Session.MTUMin / 4 ) * 3, fragsize ); // To make resends work with reduced MTU var newdata = FragmentReader.ReadBufLen(fragsize); var fragment = new DataFragment(newdata); fragment.MessageId = MessageId; fragment.IsLast = FragmentReader.Length == 0; lock ( Fragments ) { fragment.FragmentNumber = (byte)Fragments.Count; Fragments.Add(fragment); } #if LOG_ALL_TRANSPORT DebugUtils.LogDebug(() => string.Format( "SSU sending {0} fragment {1}, {2} bytes. IsLast: {3}", MessageId, fragment.FragmentNumber, fragment.Data.Length, fragment.IsLast)); #endif ++SendCount; fragment.WriteTo(writer); return(fragment); }
public DatabaseLookupMessage( I2PIdentHash key, I2PIdentHash from, LookupTypes flags, IEnumerable <I2PIdentHash> excludelist) { var excludecount = excludelist == null ? 0 : excludelist.Count(); AllocateBuffer(2 * 32 + 1 + 2 + 32 * excludecount); var writer = new BufRefLen(Payload); writer.Write(key.Hash); writer.Write(from.Hash); writer.Write8((byte)((byte)flags & ~0x01)); if (excludecount > 0) { writer.WriteFlip16((ushort)excludecount); foreach (var addr in excludelist) { writer.Write(addr.Hash); } } else { writer.Write16(0); } //dest.Add( 0 ); // Tags }
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()); }
public BufLen GetPayload() { if (!AllFragmentsFound) { throw new Exception("Cannot reassemble payload without all the fragments!"); } var messagesize = Fragments.Sum(f => f.Data.Length); const int h5inh16offset = 11; var result = new BufLen(new byte[h5inh16offset + messagesize]); var writer = new BufRefLen(result, h5inh16offset); foreach (var onef in Fragments) { writer.Write(onef.Data); } // Fake a I2NP16 header var exp = new I2PDate(SSUHost.SSUDateTime(result.PeekFlip32(1 + h5inh16offset))); result[0] = result[h5inh16offset]; result.PokeFlip64((ulong)exp, 5); result.PokeFlip16((ushort)(messagesize - 5), 13); // Not wasting time on faking checksum return(result); }
public void Receive(BufRefLen recvbuf) { if (Terminated) { throw new EndOfStreamEncounteredException(); } int len; lock ( ReceiveQueue ) { len = ReceiveQueue.Count; if (len < ReceiveQueueLengthUpperLimit) { ReceiveQueue.AddLast(recvbuf); return; } } #if DEBUG DebugUtils.LogWarning( string.Format("SSUSession {0}: ReceiveQueue is {1} messages long! Dropping new message.", DebugId, len)); #endif }
private void SaveConfig(Store s) { var lookup = s.GetMatching(e => (StoreRecordId)e[0] == StoreRecordId.StoreIdConfig, 1); var str2ix = new Dictionary <I2PString, int>(); foreach (var one in lookup) { var reader = new BufRefLen(one.Value); reader.Read32(); var key = new I2PString(reader); str2ix[key] = one.Key; } AccessConfig(delegate(Dictionary <I2PString, I2PString> settings) { foreach (var one in settings) { var rec = new BufLen[] { BufUtils.To32BL((int)StoreRecordId.StoreIdConfig), new BufLen(one.Key.ToByteArray()), new BufLen(one.Value.ToByteArray()) }; if (str2ix.ContainsKey(one.Key)) { s.Write(rec, str2ix[one.Key]); } else { s.Write(rec); } } }); }
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))); }
private void Load(string filename) { using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read)) { using (var ms = new MemoryStream()) { byte[] buf = new byte[8192]; int len; while ((len = fs.Read(buf, 0, buf.Length)) != 0) { ms.Write(buf, 0, len); } var reader = new BufRefLen(ms.ToArray()); Certificate = new I2PCertificate(reader); PrivateSigningKey = new I2PSigningPrivateKey(reader, Certificate); PublicSigningKey = new I2PSigningPublicKey(reader, Certificate); PrivateKey = new I2PPrivateKey(reader, Certificate); PublicKey = new I2PPublicKey(reader, Certificate); MyRouterIdentity = new I2PRouterIdentity(reader); Published = new I2PDate(reader); IntroKey = reader.ReadBufLen(32); } } }
public GarlicClove(BufRefLen reader) { Delivery = GarlicCloveDelivery.CreateGarlicCloveDelivery(reader); Message = I2NPMessage.ReadHeader16(reader).Message; CloveId = reader.ReadFlip32(); Expiration = new I2PDate(reader); reader.Seek(3); // Cert }
public DeliveryStatusMessage() { AllocateBuffer(12); var writer = new BufRefLen(Payload); Timestamp = new I2PDate(DateTime.UtcNow); StatusMessageId = I2NPMessage.GenerateMessageId(); }
public FragmentedMessage(II2NPHeader5 msg) { Message = msg; MessageBytes = new BufLen(msg.HeaderAndPayload); MessageId = BufUtils.RandomUint(); FragmentReader = new BufRefLen(MessageBytes); }
public DeliveryStatusMessage(ulong networkid) { AllocateBuffer(12); var writer = new BufRefLen(Payload); writer.PokeFlip64(networkid, 4); StatusMessageId = BufUtils.RandomUint(); }
public DeliveryStatusMessage(uint msgid) { AllocateBuffer(12); var writer = new BufRefLen(Payload); Timestamp = new I2PDate(DateTime.UtcNow); StatusMessageId = msgid; }
GarlicCreationInfo UseExistingSessionTags(bool explack, uint trackingid, GarlicCloveDelivery[] cloves) { Garlic msg; DeliveryStatusMessage ackmsg = null; if (explack) { msg = AddExplAck(cloves, out ackmsg); } else { var exp = new I2PDate(DateTime.UtcNow.AddMinutes(5)); msg = new Garlic(cloves.Select(d => new GarlicClove(d, exp)).ToArray()); } #if LOG_ALL_TUNNEL_TRANSFER Logging.LogDebug(() => string.Format( "DestinationSession: Garlic generated with {0} cloves. {1} tags available.", msg.Cloves.Count, SessionTags.Count)); #endif var payload = msg.ToByteArray(); var dest = new BufLen(new byte[61000]); var writer = new BufRefLen(dest, 4); // Reserve 4 bytes for GarlicMessageLength I2PSessionTag tag; lock ( SessionTags ) { var ix = BufUtils.RandomInt(SessionTags.Count); tag = SessionTags[ix]; SessionTags.RemoveAt(ix); } // Tag as header writer.Write(tag.Value); // AES block var aesstart = new BufLen(writer); var aesblock = new GarlicAESBlock(writer, null, 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), 0); return(new GarlicCreationInfo( Destination.IdentHash, cloves, new EGGarlic(new BufRefLen(dest, 0, length)), GarlicCreationInfo.KeyUsed.Aes, SessionTags.Count(), trackingid, explack ? (uint?)ackmsg.MessageId : null, LatestEGAckMessageId)); }
public override void Write(BufRefStream dest) { var header = new byte[6]; var writer = new BufRefLen(header); writer.WriteFlip16(SessionId); writer.WriteFlip32(MessageId); dest.Write(header); }
public int Send(BufRefLen writer, ConcurrentQueue <II2NPHeader16> sendqueue) { var result = 0; while (writer.Length > 10) { if (CurrentMessage == null || CurrentMessage.AllFragmentsSent) { CurrentMessage = null; lock ( sendqueue ) { if (sendqueue.IsEmpty) { return(result); } if (sendqueue.TryDequeue(out var msg)) { CurrentMessage = new FragmentedMessage(msg); } else { return(result); } } if (CurrentMessage != null) { lock ( Messages ) { Messages[CurrentMessage.MessageId] = CurrentMessage; #if LOG_MUCH_TRANSPORT Logging.LogDebugData($"SSU Message to fragment: {CurrentMessage}"); #endif } } } if (CurrentMessage.Send(writer) != null) { ++result; } if (CurrentMessage.AllFragmentsSent) { lock ( AckQueue ) { AckQueue.AddFirst(CurrentMessage); } #if LOG_MUCH_TRANSPORT Logging.LogTransport("SSU Message " + CurrentMessage.MessageId.ToString() + " all fragments sent."); #endif } } return(result); }
public override void Write(BufRefStream dest) { var header = new byte[3]; var writer = new BufRefLen(header); writer.WriteFlip16(SessionId); writer.Write8((byte)SessionState); dest.Write(header); }
public SendMessageMessage(BufRefLen reader) : base(ProtocolMessageType.SendMessage) { SessionId = reader.ReadFlip16(); Destination = new I2PDestination(reader); var len = reader.ReadFlip32(); Payload = reader.ReadBufLen((int)len); Nonce = reader.ReadFlip32(); }
static void MyDestination_DataReceived(ClientDestination dest, BufLen data) { Logging.LogInformation($"Program {UnpublishedDestination}: data received {data:20}"); var reader = new BufRefLen(data); var unzip = LZUtils.BCGZipDecompressNew((BufLen)reader); var packet = new StreamingPacket((BufRefLen)unzip); Logging.LogInformation($"Program {UnpublishedDestination}: {packet}"); }
public override SSUState HandleMessage(SSUHeader header, BufRefLen reader) { if (header.MessageType == SSUHeader.MessageTypes.RelayResponse) { var response = new RelayResponse(reader); return(HandleRelayResponse(response)); } return(this); }
public DatabaseLookupMessage(I2PIdentHash key, I2PIdentHash from, LookupTypes flags) { AllocateBuffer(2 * 32 + 1 + 2); var writer = new BufRefLen(Payload); writer.Write(key.Hash); writer.Write(from.Hash); writer.Write8((byte)((byte)flags & ~(byte)LookupTypes.Tunnel)); writer.Write16(0); }
public SSUHeader(BufRefLen reader) { MAC = reader.ReadBufLen(16); IV = reader.ReadBufLen(16); MACDataBuf = new BufLen(reader); EncryptedBuf = new BufLen(MACDataBuf, 0, MACDataBuf.Length & 0x7ffffff0); FlagBuf = reader.ReadBufLen(1); TimeStampBuf = reader.ReadBufLen(4); PostTimestampBuf = new BufLen(reader); }
static BufLen FindTheZero(BufLen start) { var result = new BufRefLen(start); while (result.Read8() != 0) { ; } return(result.View); }