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()); }
internal static BufLen Send(DHHandshakeContext context) { context.TimestampA = (uint)Math.Ceiling((DateTime.UtcNow - I2PDate.RefDate).TotalSeconds); var cleartext = new BufRefStream(); var ri = RouterContext.Inst.MyRouterIdentity.ToByteArray(); cleartext.Write(BufUtils.Flip16B((ushort)ri.Length)); cleartext.Write(ri); cleartext.Write(BufUtils.Flip32B(context.TimestampA)); Logging.LogDebugData($"SessionConfirmA send TimestampA: {I2PDate.RefDate.AddSeconds( context.TimestampA )}"); Logging.LogDebugData($"SessionConfirmA send TimestampB: {I2PDate.RefDate.AddSeconds( context.TimestampB )}"); var sign = I2PSignature.DoSign(RouterContext.Inst.PrivateSigningKey, context.X.Key, context.Y.Key, context.RemoteRI.IdentHash.Hash, BufUtils.Flip32BL(context.TimestampA), BufUtils.Flip32BL(context.TimestampB)); var padsize = BufUtils.Get16BytePadding((int)(sign.Length + cleartext.Length)); cleartext.Write(BufUtils.RandomBytes(padsize)); cleartext.Write(sign); var buf = new BufLen(cleartext.ToArray()); context.Encryptor.ProcessBytes(buf); return(buf); }
internal static void Receive(DHHandshakeContext context, I2PKeysAndCert ri) { var responselength = ri.Certificate.SignatureLength; responselength += BufUtils.Get16BytePadding(responselength); var data = context.Client.BlockReceive(responselength); context.Dectryptor.ProcessBytes(data); var signature = new I2PSignature(new BufRefLen(data), context.RemoteRI.Certificate); if (!I2PSignature.SupportedSignatureType(context.RemoteRI.Certificate.SignatureType)) { throw new SignatureCheckFailureException("NTCP SessionConfirmB recv not supported signature type: " + context.RemoteRI.Certificate.SignatureType.ToString()); } var ok = I2PSignature.DoVerify(context.RemoteRI.SigningPublicKey, signature, context.X.Key, context.Y.Key, RouterContext.Inst.MyRouterIdentity.IdentHash.Hash, BufUtils.Flip32BL(context.TimestampA), BufUtils.Flip32BL(context.TimestampB)); #if LOG_ALL_TRANSPORT DebugUtils.Log("SessionConfirmB: " + context.RemoteRI.Certificate.SignatureType.ToString() + " signature check: " + ok.ToString()); #endif if (!ok) { throw new SignatureCheckFailureException("NTCP SessionConfirmB recv sig check failure"); } }
internal static BufLen Send(DHHandshakeContext context) { context.TimestampA = (uint)Math.Ceiling((DateTime.UtcNow - I2PDate.RefDate).TotalSeconds); var cleartext = new List <byte>(); var ri = RouterContext.Inst.MyRouterIdentity.ToByteArray(); cleartext.AddRange(BufUtils.Flip16B((ushort)ri.Length)); cleartext.AddRange(ri); cleartext.AddRange(BufUtils.Flip32B(context.TimestampA)); #if LOG_ALL_TRANSPORT DebugUtils.Log("SessionConfirmA send TimestampA: " + (I2PDate.RefDate.AddSeconds(context.TimestampA).ToString())); DebugUtils.Log("SessionConfirmA send TimestampB: " + (I2PDate.RefDate.AddSeconds(context.TimestampB).ToString())); #endif var sign = I2PSignature.DoSign(RouterContext.Inst.PrivateSigningKey, context.X.Key, context.Y.Key, context.RemoteRI.IdentHash.Hash, BufUtils.Flip32BL(context.TimestampA), BufUtils.Flip32BL(context.TimestampB)); var padsize = BufUtils.Get16BytePadding(sign.Length + cleartext.Count); cleartext.AddRange(BufUtils.Random(padsize)); cleartext.AddRange(sign); var buf = new BufLen(cleartext.ToArray()); context.Encryptor.ProcessBytes(buf); return(buf); }
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.Random(padding)); var baddr = new BufLen(Session.RemoteEP.Address.GetAddressBytes()); var bport = BufUtils.Flip16BL((ushort)Session.RemoteEP.Port); #if LOG_ALL_TRANSPORT Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: X for signature {1}.", Session.DebugId, Request.X.Key)); Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Y for signature {1}.", Session.DebugId, Request.Y.Key)); Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Alice address for signature {1}. Port {2}.", Session.DebugId, Request.SCMessage.Address, Request.SCMessage.Port)); Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Bob address for signature {1}. Port {2}.", Session.DebugId, baddr, bport)); Logging.LogTransport(string.Format("SSU SessionConfirmedState {0}: Relay tag {1}. Signon time {2}.", Session.DebugId, Request.SCMessage.RelayTag, (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, (BufLen)Session.SignOnTimeA ); writer.Write(sign); #if LOG_ALL_TRANSPORT Logging.LogTransport(string.Format("SessionConfirmedState {0}: sending unfragmented SessionConfirmed. {1} bytes [0x{1:X}].", Session.DebugId, writer - start - SSUHeader.FIXED_HEADER_SIZE)); #endif return(true); }); }
private SSUState VerifyRemoteSignature() { var baaddr = new BufLen(AAddr); var bbport = BufUtils.Flip16BL((ushort)Session.MyRouterContext.UDPPort); #if LOG_ALL_TRANSPORT DebugUtils.Log(string.Format("SSU SessionCreatedState {0}: X for signature {1}.", Session.DebugId, Request.X)); DebugUtils.Log(string.Format("SSU SessionCreatedState {0}: Y for signature {1}.", Session.DebugId, Y.Key)); DebugUtils.Log(string.Format("SSU SessionCreatedState {0}: Alice address for signature {1}. Port {2}.", Session.DebugId, baaddr, (BufLen)APort)); DebugUtils.Log(string.Format("SSU SessionCreatedState {0}: Bob address for signature {1}. Port {2}.", Session.DebugId, Request.Address, bbport)); DebugUtils.Log(string.Format("SSU SessionCreatedState {0}: Relay tag {1}. Signon time {2}.", Session.DebugId, (BufLen)RelayTag, (BufLen)ASignonTime)); #endif var signdata = new BufLen[] { Request.X, Y.Key, baaddr, (BufLen)APort, Request.Address, bbport, (BufLen)RelayTag, (BufLen)ASignonTime }; var ok = I2PSignature.DoVerify(Session.RemoteRouter.SigningPublicKey, ASign, signdata); #if LOG_ALL_TRANSPORT DebugUtils.Log("SSU SessionCreatedState " + Session.DebugId + ": " + Session.RemoteRouter.Certificate.SignatureType.ToString() + " signature check: " + ok.ToString()); #endif if (!ok) { throw new SignatureCheckFailureException("SSU SessionCreatedState recv sig check failure"); } DebugUtils.Log("SSU SessionCreatedState: Session " + Session.DebugId + " established. Moving to Established state."); var next = new EstablishedState(Session); Session.ReportConnectionEstablished(); if (NetDb.Inst != null) { NetDb.Inst.Statistics.SuccessfulConnect(Session.RemoteRouter.IdentHash); } return(next); }
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); }); }
public StreamingPacket(BufRefLen reader) { SendStreamId = reader.ReadFlip32(); ReceiveStreamId = reader.ReadFlip32(); SequenceNumber = reader.ReadFlip32(); AckTrhough = reader.ReadFlip32(); NACKs = new List <uint>(); var nackcount = reader.Read8(); for (int i = 0; i < nackcount; ++i) { NACKs.Add(reader.ReadFlip32()); } ResendDelay = reader.Read8(); Flags = (PacketFlags)reader.ReadFlip16(); var optionsize = reader.ReadFlip16(); // Options order // DELAY_REQUESTED // FROM_INCLUDED if ((Flags & PacketFlags.FROM_INCLUDED) != 0) { From = new I2PDestination(reader); } // MAX_PACKET_SIZE_INCLUDED if ((Flags & PacketFlags.MAX_PACKET_SIZE_INCLUDED) != 0) { var mtu = reader.ReadFlip16(); } // OFFLINE_SIGNATURE // SIGNATURE_INCLUDED if ((Flags & PacketFlags.SIGNATURE_INCLUDED) != 0) { Signature = new I2PSignature(reader, From.Certificate); } Payload = reader.ReadBufLen(reader.Length); }
private SSUState VerifyRemoteSignature() { var baaddr = new BufLen(AAddr); var bbport = BufUtils.Flip16BL((ushort)Session.MyRouterContext.UDPPort); #if LOG_MUCH_TRANSPORT Logging.LogTransport($"SSU {this}: X for signature {Request.X}."); Logging.LogTransport($"SSU {this}: Y for signature {Y.Key}."); Logging.LogTransport($"SSU {this}: Alice address for signature {baaddr}. Port {(BufLen)APort}."); Logging.LogTransport($"SSU {this}: Bob address for signature {Request.Address}. Port {bbport}."); Logging.LogTransport($"SSU {this}: Relay tag {(BufLen)RelayTag}. Signon time {(BufLen)ASignonTime}."); #endif var signdata = new BufLen[] { Request.X, Y.Key, baaddr, BufUtils.To16BL(APort), Request.Address, bbport, BufUtils.To32BL(RelayTag), BufUtils.To32BL(ASignonTime) }; var ok = I2PSignature.DoVerify(Session.RemoteRouter.SigningPublicKey, ASign, signdata); Logging.LogTransport($"SSU SessionCreatedState {Session.DebugId}: " + $"{Session.RemoteRouter.Certificate.SignatureType} " + $"signature check: {ok}"); if (!ok) { throw new SignatureCheckFailureException("SSU SessionCreatedState recv sig check failure"); } Logging.LogTransport("SSU SessionCreatedState: Session " + Session.DebugId + " established. Moving to Established state."); var next = new EstablishedState(Session); Session.ReportConnectionEstablished(); NetDb.Inst.Statistics.SuccessfulConnect(Session.RemoteRouter.IdentHash); return(next); }
private SSUState AssembleFragments(SSUHeader header, BufRefLen reader, byte info, ushort cursize) { var fragnr = info >> 4; var fragcount = info & 0x0f; Logging.LogTransport($"AssembleFragments: frag {fragnr} / {fragcount}, len {cursize}."); if (fragnr != fragcount - 1) { Fragments[fragnr] = reader.ReadBufLen(cursize); } else { ASignonTime = reader.Peek32(cursize); Fragments[fragnr] = reader.ReadBufLen(reader.Length); } if (Fragments.Any(f => f is null)) { return(this); } var buf = new BufLen(new byte[Fragments.Sum(f => f.Length)]); var bufwriter = new BufRefLen(buf); for (int i = 0; i < Fragments.Length; ++i) { bufwriter.Write(Fragments[i]); } Session.RemoteRouter = new I2PRouterIdentity((BufRefLen)buf); var signbuf = new BufRefLen(buf, buf.Length - Session.RemoteRouter.Certificate.SignatureLength); ASign = new I2PSignature(signbuf, Session.RemoteRouter.Certificate); return(VerifyRemoteSignature()); }
internal static byte[] Send(DHHandshakeContext context) { var msglen = RouterContext.Inst.MyRouterIdentity.Certificate.SignatureLength; msglen += BufUtils.Get16BytePadding(msglen); var writer = new BufRefLen(new byte[msglen]); var SigBuf = I2PSignature.DoSign(RouterContext.Inst.PrivateSigningKey, context.XBuf, context.YBuf, context.RemoteRI.IdentHash.Hash, (BufLen)BufUtils.Flip32(context.TimestampA), (BufLen)BufUtils.Flip32(context.TimestampB)); writer.Write(SigBuf); writer.Write(BufUtils.Random(writer.Length)); writer.Reset(); context.Encryptor.ProcessBytes((BufLen)writer); return(writer.ToByteArray()); }
private SSUState ParseSessionConfirmed(SSUHeader header, BufRefLen reader) { var info = reader.Read8(); var cursize = reader.ReadFlip16(); if (Fragments != null) { return(AssembleFragments(header, reader, info, cursize)); } if ((info & 0x0f) == 1) { var cursizedata = reader.ReadBufRefLen(cursize); Session.RemoteRouter = new I2PRouterIdentity(cursizedata); ASignonTime = reader.Read32(); reader.Seek(reader.Length - Session.RemoteRouter.Certificate.SignatureLength); ASign = new I2PSignature(reader, Session.RemoteRouter.Certificate); return(VerifyRemoteSignature()); } Fragments = new List <BufLen>(new BufLen[info & 0x0f]); return(AssembleFragments(header, reader, info, cursize)); }
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), (BufLen)APort, Request.Address, (BufLen)BufUtils.Flip16((ushort)Session.MyRouterContext.UDPPort), (BufLen)RelayTag, (BufLen)Session.SignOnTimeB); var signstart = new BufLen(writer); writer.Write(sign); var padding = BufUtils.Get16BytePadding(writer - signstart); writer.Write(BufUtils.Random(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); }); }
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) { #if LOG_ALL_TRANSPORT Logging.LogTransport(string.Format("SessionConfirmedState {0}: sending fragment {1} of {2}, {3} bytes [0x{3:X}].", Session.DebugId, i + 1, datafragments.Count + 1, datafragments[i].Length)); #endif 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.Random(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, (BufLen)Session.SignOnTimeA ); writer.Write(sign); #if LOG_ALL_TRANSPORT Logging.LogTransport(string.Format("SessionConfirmedState {0}: sending fragment {1} of {2}, {3} bytes [0x{3:X}].", Session.DebugId, frag + 1, datafragments.Count + 1, writer - start - SSUHeader.FIXED_HEADER_SIZE)); #endif return(true); }); }
internal static void Receive(DHHandshakeContext context, BufLen datastart) { var origbuf = new BufRefLen(datastart); var reader = new BufRefLen(datastart); context.Dectryptor.ProcessBytes(datastart); var rilen = reader.ReadFlip16(); var ribuf = reader.ReadBufRefLen(rilen); context.TimestampA = reader.ReadFlip32(); #if LOG_ALL_TRANSPORT DebugUtils.Log("SessionConfirmA recv TimestampA: " + (I2PDate.RefDate.AddSeconds(context.TimestampA).ToString())); DebugUtils.Log("SessionConfirmA recv TimestampB: " + (I2PDate.RefDate.AddSeconds(context.TimestampB).ToString())); #endif context.RemoteRI = new I2PRouterIdentity(ribuf); context.RunContext.RemoteRouterIdentity = context.RemoteRI; var sizeofpayload = 2 + rilen + 4 + context.RemoteRI.Certificate.SignatureLength; var paddingsize = BufUtils.Get16BytePadding(sizeofpayload); reader.Seek(paddingsize); var sigstart = new BufLen(reader, 0, context.RemoteRI.Certificate.SignatureLength); var needbytes = 2 + context.RemoteRI.Certificate.RouterIdentitySize + 4 + context.RemoteRI.Certificate.SignatureLength; needbytes += BufUtils.Get16BytePadding(needbytes); var writer = new BufRef(origbuf, origbuf.Length); var gotbytes = writer - origbuf; if (gotbytes < needbytes) { #if LOG_ALL_TRANSPORT DebugUtils.Log("SessionConfirmA recv not enough data: " + datastart.Length.ToString() + ". I want " + needbytes.ToString() + " bytes."); #endif var buf = context.Client.BlockReceive(needbytes - gotbytes); writer.Write(buf); } if (needbytes - datastart.Length > 0) { context.Dectryptor.ProcessBytes(new BufLen(datastart, datastart.Length, needbytes - datastart.Length)); } var signature = new I2PSignature(new BufRefLen(sigstart), context.RemoteRI.Certificate); if (!I2PSignature.SupportedSignatureType(context.RemoteRI.Certificate.SignatureType)) { throw new SignatureCheckFailureException("NTCP SessionConfirmA recv not supported signature type: " + context.RemoteRI.Certificate.SignatureType.ToString()); } var sigok = I2PSignature.DoVerify( context.RemoteRI.SigningPublicKey, signature, context.XBuf, context.YBuf, RouterContext.Inst.MyRouterIdentity.IdentHash.Hash, new BufLen(BufUtils.Flip32B(context.TimestampA)), new BufLen(BufUtils.Flip32B(context.TimestampB)) ); #if LOG_ALL_TRANSPORT DebugUtils.Log("SessionConfirmA recv: " + context.RemoteRI.Certificate.SignatureType.ToString() + " signature check: " + sigok.ToString() + "."); #endif if (!sigok) { throw new SignatureCheckFailureException("NTCP SessionConfirmA recv signature check fail"); } }
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); }); }
public override SSUState HandleMessage(SSUHeader header, BufRefLen reader) { var tstime = SSUHost.SSUDateTime(header.TimeStamp); if (header.MessageType != SSUHeader.MessageTypes.SessionCreated) { #if LOG_ALL_TRANSPORT Logging.LogTransport("SSU SessionRequestState: Received unexpected message " + tstime.ToString() + " : " + header.Flag.ToString()); #endif 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 Session.SharedKey, out Session.MACKey, Y.ToBigInteger().ModPow(PrivateKey.ToBigInteger(), I2PConstants.ElGamalP)); 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)); #if LOG_ALL_TRANSPORT Logging.LogTransport("SSU SessionRequestState " + Session.DebugId + " : Received SessionCreated. " + tstime.ToString() + " : " + btime.ToString()); #endif 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.ToString()); } 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); #if LOG_ALL_TRANSPORT Logging.LogTransport("SSU SessionRequestState: Signature check: " + sok.ToString() + ". " + Session.RemoteRouter.Certificate.SignatureType.ToString()); #endif if (!sok) { throw new SignatureCheckFailureException("SSU SessionRequestState " + Session.DebugId + ": Received SessionCreated signature check failed." + Session.RemoteRouter.Certificate.ToString()); } var relaytag = SCMessage.RelayTag.PeekFlip32(0); if (relaytag != 0) { Session.Host.IntroductionRelayOffered( new IntroducerInfo( Session.RemoteEP.Address, (ushort)Session.RemoteEP.Port, Session.IntroKey, relaytag)); } Logging.LogTransport("SSU SessionRequestState: Session " + Session.DebugId + " created. Moving to SessionConfirmedState."); Session.ReportConnectionEstablished(); return(new SessionConfirmedState(Session, this)); }
internal override I2CPState MessageReceived(I2CPMessage msg) { try { switch (msg) { case CreateSessionMessage csm: Logging.LogDebug($"{this}: Received message {csm}."); var signok = I2PSignature.DoVerify( csm.Config.Destination.SigningPublicKey, csm.Config.Signature, csm.Config.SignedBuf); if (!signok) { Logging.LogWarning($"{this} CreateSessionMessage: Signature check failed."); Session.Send(new SessionStatusMessage(0, SessionStates.Invalid)); return(this); } var newdest = Router.CreateDestination( csm.Config.Destination, null, !csm.Config.DontPublishLeaseSet, out var alreadyrunning); if (alreadyrunning || newdest is null) { Logging.LogWarning($"{this}: Destination already running. {csm}"); Session.Send(new SessionStatusMessage(0, SessionStates.Refused)); return(this); } var newsession = Session.GenerateNewSessionId(); newsession.MyDestination = newdest; newsession.Config = csm.Config; UpdateConfiguration(newsession, csm.Config); Session.AttachDestination(newsession.MyDestination); Logging.LogDebug($"{this}: Creating session {newsession.SessionId}."); var reply = new SessionStatusMessage(newsession.SessionId, SessionStates.Created); Session.Send(reply); Session.SendPendingLeaseUpdates(true); break; case ReconfigureSessionMessage rcm: var rcms = Session.SessionIds[rcm.SessionId]; rcms.Config = rcm.Config; UpdateConfiguration(rcms, rcms.Config); break; case CreateLeaseSetMessage clsm: Logging.LogDebug($"{this}: {clsm} {clsm.PrivateKey}"); var s = Session.SessionIds[clsm.SessionId]; s.PrivateKey = clsm.PrivateKey; s.MyDestination.TemporaryPrivateKey = clsm.PrivateKey; s.LeaseInfo = clsm.Info; s.MyDestination.SignedLeases = clsm.Leases; Session.SendPendingLeaseUpdates(true); break; case DestLookupMessage dlum: Logging.LogDebug($"{this}: {dlum} {dlum.Ident.Id32Short}"); Session .SessionIds .First() .Value .MyDestination .LookupDestination(dlum.Ident, HandleDestinationLookupResult, null); break; case HostLookupMessage hlum: Logging.LogDebug($"{this}: {hlum} {hlum.SessionId} {hlum.RequestId} {hlum.Hash?.Id32Short}"); I2PIdentHash lookuphash; if (hlum.RequestType == HostLookupMessage.HostLookupTypes.HostName) { lookuphash = ParseHostName(hlum); if (lookuphash is null) { Session.Send(new HostReplyMessage( hlum.SessionId, hlum.RequestId, HostLookupResults.Failure)); break; } } else { lookuphash = hlum.Hash; } if (hlum.SessionId == 0xFFFF) { Router.LookupDestination( lookuphash, HandleHostLookupResult, new HostLookupInfo { RequestId = hlum.RequestId, SessionId = hlum.SessionId }); } else { var s2 = Session.SessionIds[hlum.SessionId]; s2.MyDestination.LookupDestination( lookuphash, HandleHostLookupResult, new HostLookupInfo { RequestId = hlum.RequestId, SessionId = hlum.SessionId }); } break; case SendMessageMessage smm: Logging.LogDebugData($"{this}: {smm} {smm.Destination.IdentHash.Id32Short} {smm.Payload}"); SendMessageToDestination( smm.Destination, smm.SessionId, smm.Payload, smm.Nonce); break; case SendMessageExpiresMessage smem: Logging.LogDebugData($"{this}: {smem} {smem.Destination.IdentHash.Id32Short} {(PayloadFormat)smem.Payload[9]} {smem.Payload}"); SendMessageToDestination( smem.Destination, smem.SessionId, smem.Payload, smem.Nonce); break; case DestroySessionMessage dsm: Logging.LogDebug($"{this}: {dsm}"); Session.Send(new SessionStatusMessage(dsm.SessionId, SessionStates.Destroyed)); return(null); default: Logging.LogWarning($"{this}: Unhandled message {msg}"); break; } return(this); } catch (Exception ex) { Logging.LogWarning($"{this} MessageReceived: {msg.MessageType} {ex}"); throw; } }
public void Write(BufRefStream dest) { // Not including options var headersize = 4 * 4 + 1 + NACKs.Count * 4 + 1 + 2 + 2; // Options var optionssize = (Flags & PacketFlags.FROM_INCLUDED) != 0 ? From.Size : 0; optionssize += (Flags & PacketFlags.SIGNATURE_INCLUDED) != 0 ? From.SigningPublicKey.Certificate.SignatureLength : 0; optionssize += (Flags & PacketFlags.MAX_PACKET_SIZE_INCLUDED) != 0 ? 2 : 0; optionssize += (Flags & PacketFlags.DELAY_REQUESTED) != 0 ? 2 : 0; var header = new BufLen(new byte[headersize + optionssize]); var writer = new BufRefLen(header); writer.WriteFlip32(SendStreamId); writer.WriteFlip32(ReceiveStreamId); writer.WriteFlip32(SequenceNumber); writer.WriteFlip32(AckTrhough); writer.Write8((byte)NACKs.Count); foreach (var nak in NACKs) { writer.WriteFlip32(nak); } writer.Write8(ResendDelay); writer.WriteFlip16((ushort)Flags); writer.WriteFlip16((ushort)optionssize); // Options order // DELAY_REQUESTED // FROM_INCLUDED if ((Flags & PacketFlags.FROM_INCLUDED) != 0) { writer.Write(From.ToByteArray()); } // MAX_PACKET_SIZE_INCLUDED if ((Flags & PacketFlags.MAX_PACKET_SIZE_INCLUDED) != 0) { writer.WriteFlip16(MTU); } // OFFLINE_SIGNATURE // SIGNATURE_INCLUDED if ((Flags & PacketFlags.SIGNATURE_INCLUDED) != 0) { writer.Write(I2PSignature.DoSign(SigningKey, header)); } #if DEBUG if (writer.Length != 0) { throw new InvalidOperationException("StreamingPacket Write buffer size error"); } #endif dest.Write((BufRefLen)header); dest.Write((BufRefLen)Payload); }