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); }
private PeerTestState(SSUHost host, I2PRouterInfo router) { Host = host; Router = router; Session = (SSUSession)Host.AddSession(router); //Session.StartPeerTest( this ); }
private PeerTestState(SSUHost host, I2PRouterAddress addr, I2PKeysAndCert dest) { Host = host; Addr = addr; Dest = dest; Session = (SSUSession)Host.AddSession(addr, dest); //Session.StartPeerTest( this ); }
public SSUHeader(BufRef writer, MessageTypes msgtype) { MAC = writer.ReadBufLen(16); IV = writer.ReadBufLen(16); IV.Randomize(); FlagBuf = writer.ReadBufLen(1); MessageType = msgtype; TimeStampBuf = writer.ReadBufLen(4); TimeStamp = SSUHost.SSUTime(DateTime.UtcNow); }
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); switch (macstate) { case MACHealth.AbandonSession: Logging.LogTransport($"SSU {this}: Abandoning session. MAC check failed."); SendSessionDestroyed(); Session.Host.ReportEPProblem(RemoteEP); return(null); case MACHealth.Missmatch: return(this); } // Decrypt Cipher.Init(false, CurrentPayloadKey.ToParametersWithIV(header.IV)); Cipher.ProcessBytes(recvencr); header.SkipExtendedHeaders(reader); if (header.MessageType == SSUHeader.MessageTypes.SessionDestroyed && CurrentPayloadKey != Session.RemoteIntroKey && CurrentPayloadKey != Session.MyRouterContext.IntroKey) { Logging.LogTransport($"SSU {this}: Received SessionDestroyed."); SendSessionDestroyed(); return(null); } Logging.LogDebugData($"SSU {this}: Received message: {header.MessageType}" + $": {SSUHost.SSUDateTime( header.TimeStamp )}"); DataReceived(); return(HandleMessage(header, reader)); }
private void SendUnfragmentedSessionConfirmed() { var ri = new BufLen(Session.MyRouterContext.MyRouterInfo.ToByteArray()); SendMessage( SSUHeader.MessageTypes.SessionConfirmed, Session.MACKey, Session.SharedKey, (start, writer) => { writer.Write8((byte)((0 << 4) + 1)); writer.WriteFlip16((ushort)ri.Length); writer.Write(ri); Session.SignOnTimeA = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow)); writer.Write32(Session.SignOnTimeA); var padding = BufUtils.Get16BytePadding(Session.MyRouterContext.Certificate.SignatureLength + (writer - start)); writer.Write(BufUtils.RandomBytes(padding)); var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes()); var bport = BufUtils.Flip16BL((ushort)Session.RemoteEP.Port); #if LOG_MUCH_TRANSPORT Logging.LogTransport($"SSU {this}: X for signature {Request.X.Key}."); Logging.LogTransport($"SSU {this}: Y for signature {Request.Y.Key}."); Logging.LogTransport($"SSU {this}: Alice address for signature {Request.SCMessage.Address}. Port {Request.SCMessage.Port}."); Logging.LogTransport($"SSU {this}: Bob address for signature {baddr}. Port {bport}."); Logging.LogTransport($"SSU {this}: Relay tag {Request.SCMessage.RelayTag}. Signon time {(BufLen)Session.SignOnTimeA}."); #endif var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey, Request.X.Key, Request.Y.Key, Request.SCMessage.Address, Request.SCMessage.Port, baddr, bport, Request.SCMessage.RelayTag, BufUtils.To32BL(Session.SignOnTimeA) ); writer.Write(sign); Logging.LogTransport($"SSU {this}: {Session.RemoteEP} " + $"sending unfragmented SessionConfirmed [0x{writer - start - SSUHeader.FIXED_HEADER_SIZE:X}] bytes."); return(true); }); }
private void SendSessionCreated() { SendMessage( SSUHeader.MessageTypes.SessionCreated, Session.MyRouterContext.IntroKey, Session.MyRouterContext.IntroKey, (start, writer) => { writer.Write(Y.Key); AAddr = Session.RemoteEP.Address.GetAddressBytes(); writer.Write8((byte)AAddr.Length); writer.Write(AAddr); APort = BufUtils.Flip16((ushort)Session.RemoteEP.Port); writer.Write16(APort); writer.WriteFlip32(RelayTag); Session.SignOnTimeB = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow)); writer.Write32(Session.SignOnTimeB); var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey, Request.X, Y.Key, new BufLen(AAddr), BufUtils.To16BL(APort), Request.Address, BufUtils.Flip16BL((ushort)Session.MyRouterContext.UDPPort), BufUtils.To32BL(RelayTag), BufUtils.To32BL(Session.SignOnTimeB)); var signstart = new BufLen(writer); writer.Write(sign); var padding = BufUtils.Get16BytePadding(writer - signstart); writer.Write(BufUtils.RandomBytes(padding)); var cipher = new CbcBlockCipher(new AesEngine()); var signcryptbuf = new BufLen(signstart, 0, writer - signstart); cipher.Init(true, Session.SharedKey.ToParametersWithIV(new BufLen(start, 16, 16))); cipher.ProcessBytes(signcryptbuf); return(true); }); }
public override SSUState HandleMessage(SSUHeader header, BufRefLen reader) { var tstime = SSUHost.SSUDateTime(header.TimeStamp); if (header.MessageType != SSUHeader.MessageTypes.SessionCreated) { Logging.LogTransport($"SSU SessionRequestState: Received unexpected message {tstime} : {header.Flag}"); 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 var sessionkey, out var mackey, Y.ToBigInteger().ModPow(PrivateKey.ToBigInteger(), I2PConstants.ElGamalP)); Session.SharedKey = sessionkey; Session.MACKey = mackey; 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)); Logging.LogTransport($"SSU SessionRequestState {Session.DebugId} : Received SessionCreated. {tstime.ToString()} : {btime}"); 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}"); } 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); Logging.LogTransport($"SSU SessionRequestState: Signature check: {sok}. {Session.RemoteRouter.Certificate.SignatureType}"); if (!sok) { throw new SignatureCheckFailureException($"SSU SessionRequestState {Session.DebugId}: Received SessionCreated signature check failed." + Session.RemoteRouter.Certificate.ToString()); } if (!RemoteIsFirewalled) { var relaytag = SCMessage.RelayTag.PeekFlip32(0); if (relaytag != 0) { Session.RemoteIntroducerInfo = new IntroducerInfo( Session.RemoteEP.Address, (ushort)Session.RemoteEP.Port, Session.RemoteIntroKey, relaytag); Session.Host.IntroductionRelayOffered(Session.RemoteIntroducerInfo); } } Logging.LogTransport($"SSU {this}: SessionCreated received " + $"from {Session.RemoteEP} created. Moving to SessionConfirmedState."); Session.ReportConnectionEstablished(); return(new SessionConfirmedState(Session, this)); }
private void SendFragmentedSessionConfirmed() { var ri = new BufLen(Session.MyRouterContext.MyRouterInfo.ToByteArray()); var rireader = new BufRefLen(ri); var datafragments = new List <BufLen>(); while (rireader.Length > 0) { datafragments.Add(rireader.ReadBufLen(Math.Min(rireader.Length, 472))); } for (int i = 0; i < datafragments.Count; ++i) { Logging.LogTransport($"SSU {this}: {Session.RemoteEP} " + $"sending fragment {i + 1} of {datafragments.Count + 1}, [0x{datafragments[i].Length:X}] bytes."); SendMessage( SSUHeader.MessageTypes.SessionConfirmed, Session.MACKey, Session.SharedKey, (start, writer) => { writer.Write8((byte)((i << 4) + datafragments.Count + 1)); writer.WriteFlip16((ushort)datafragments[i].Length); writer.Write(datafragments[i]); return(true); }); } SendMessage( SSUHeader.MessageTypes.SessionConfirmed, Session.MACKey, Session.SharedKey, (start, writer) => { var frag = datafragments.Count; writer.Write8((byte)((frag << 4) + frag + 1)); writer.WriteFlip16(0); Session.SignOnTimeA = BufUtils.Flip32(SSUHost.SSUTime(DateTime.UtcNow)); writer.Write32(Session.SignOnTimeA); var padding = BufUtils.Get16BytePadding(Session.MyRouterContext.Certificate.SignatureLength + (writer - start)); writer.Write(BufUtils.RandomBytes(padding)); var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes()); var sign = I2PSignature.DoSign(Session.MyRouterContext.PrivateSigningKey, Request.X.Key, Request.Y.Key, Request.SCMessage.Address, Request.SCMessage.Port, baddr, BufUtils.Flip16BL((ushort)Session.RemoteEP.Port), Request.SCMessage.RelayTag, BufUtils.To32BL(Session.SignOnTimeA) ); writer.Write(sign); Logging.LogTransport($"SSU {this}: {Session.RemoteEP} " + $"sending fragment {frag + 1} of {datafragments.Count + 1}, [0x{writer - start - SSUHeader.FIXED_HEADER_SIZE:X}] bytes."); return(true); }); }