public override void Write(BufRefStream dest) { dest.Write((BufRefLen)BufUtils.Flip16BL(SessionId)); dest.Write(TwentyBytes); PrivateKey.Write(dest); Leases.Write(dest); }
public PeerTest(BufLen nonce, IPAddress aliceip, int aliceport, BufLen introkey) { TestNonce = nonce; var ab = aliceip.GetAddressBytes(); AliceIPAddrSize = (BufLen)(byte)ab.Length; AliceIPAddr = new BufLen(ab); AlicePort = BufUtils.Flip16BL((ushort)aliceport); IntroKey = introkey; }
protected MACHealth VerifyMAC(SSUHeader header, BufLen key) { var macdata = new BufLen[] { header.MACDataBuf, header.IV, BufUtils.Flip16BL((ushort)((ushort)header.MACDataBuf.Length ^ I2PConstants.SSU_PROTOCOL_VERSION)) }; var recvhash = I2PHMACMD5Digest.Generate(macdata, key, MACBuf); var ok = header.MAC.Equals(recvhash); if (ok) { IntroMACsReceived = 0; } else { DebugUtils.LogDebug(() => string.Format("SSU {0}: {1} Current MAC check fail. Payload {2} bytes. ", this, Session.DebugId, header.MACDataBuf.Length)); if ((int)DebugUtils.LogLevel <= (int)DebugUtils.LogLevels.Debug) { if (Session.IntroKey != null) { var recvhashi = I2PHMACMD5Digest.Generate(macdata, new BufLen(Session.IntroKey), MACBuf); var oki = header.MAC.Equals(recvhashi); DebugUtils.Log("SSU " + this.ToString() + ": " + Session.DebugId + ". " + "Session Intro key match: " + oki.ToString()); } } var recvhash2 = I2PHMACMD5Digest.Generate(macdata, new BufLen(Session.MyRouterContext.IntroKey), MACBuf); var ok2 = header.MAC.Equals(recvhash2); DebugUtils.LogDebug(() => string.Format("SSU {0}: {1} My intro MAC key match: {3}. Payload {2} bytes. ", this, Session.DebugId, header.MACDataBuf.Length, ok2)); if (ok2) { if (++IntroMACsReceived > 5) { var reason = string.Format("SSU {0}: {1}. {2} intro key matches in a row. The other side seems to have started a new session.", this, Session.DebugId, IntroMACsReceived); DebugUtils.Log(reason); return(MACHealth.AbandonSession); } return(MACHealth.UseOurIntroKey); } } return(ok ? MACHealth.Match : MACHealth.Missmatch); }
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); }
protected MACHealth VerifyMAC(SSUHeader header, BufLen key) { var macdata = new BufLen[] { header.MACDataBuf, header.IV, BufUtils.Flip16BL((ushort)((ushort)header.MACDataBuf.Length ^ I2PConstants.SSU_PROTOCOL_VERSION)) }; var recvhash = I2PHMACMD5Digest.Generate(macdata, key, MACBuf); var ok = header.MAC.Equals(recvhash); var result = ok ? MACHealth.Match : MACHealth.Missmatch; if (!ok) { if (++ConsecutiveMACCheckFailures > 3) { result = MACHealth.AbandonSession; } } else { ConsecutiveMACCheckFailures = 0; } #if DEBUG if (result != MACHealth.Match) { Logging.LogTransport($"SSU {this}: VerifyMAC {result} [{ConsecutiveMACCheckFailures}] {key}"); } else { Logging.LogDebugData($"SSU {this}: VerifyMAC {result} [{ConsecutiveMACCheckFailures}] {key}"); } #endif #if DEBUG && SSU_TRACK_OLD_MAC_KEYS if (result != MACHealth.Match) { result = CheckOldKeys(header, macdata, MACBuf, result); } #endif return(result); }
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 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 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); }); }
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); }); }
/** * From PacketBuilder.java * -----8<----- * @param packet prepared packet with the first 32 bytes empty and a length * whose size is mod 16. * As of 0.9.7, length non-mod-16 is allowed; the * last 1-15 bytes are included in the MAC calculation but are not encrypted. * -----8<----- */ protected void SendMessage( IPEndPoint dest, SSUHeader.MessageTypes message, BufLen mackey, BufLen cryptokey, SendMessageGenerator gen, SendMessageGenerator genextrapadding) { var start = Session.Host.SendBuffers.Pop(); var writer = new BufRefLen(start); var header = new SSUHeader(writer, message); if (!gen(start, writer)) { return; } // Do not cut to datalen & ~0xf as that might make data at the end unencrypted var datapadding = BufUtils.Get16BytePadding(writer - start); writer.Write(BufUtils.RandomBytes(datapadding)); var datalen = writer - start; var encryptedbuf = new BufLen(start, 32, datalen - 32); // TODO: Adding extra padding does not seem to work if (genextrapadding != null) { if (!genextrapadding(start, writer)) { return; } } var packetlen = writer - start; var data = new BufLen(start, 0, packetlen); var hmac = new BufLen(data, 32); SendMessageCipher.Init(true, cryptokey.ToParametersWithIV(header.IV)); SendMessageCipher.ProcessBytes(encryptedbuf); I2PHMACMD5Digest.Generate(new BufLen[] { hmac, header.IV, BufUtils.Flip16BL((ushort)((ushort)hmac.Length ^ I2PConstants.SSU_PROTOCOL_VERSION)) }, mackey, header.MAC); #if LOG_MUCH_TRANSPORT Logging.LogTransport(string.Format("SSUState SendMessage {0}: encrlen {1} bytes [0x{1:X}] (padding {2} bytes [0x{2:X}]), " + "hmac {3} bytes [0x{3:X}], sendlen {4} bytes [0x{4:X}]", Session.DebugId, encryptedbuf.Length, datapadding, hmac.Length, data.Length)); #endif DataSent(); Send(dest, data); }
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)); }
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 void Write(BufRefStream dest) { dest.Write((BufRefLen)BufUtils.Flip16BL(SessionId)); }