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 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)); }
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)); }