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); }
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 MACHealth CheckOldKeys( SSUHeader header, BufLen[] macdata, BufLen mACBuf, MACHealth result) { if (!SSUSession.OldKeys.TryGetValue(Session.RemoteEP, out var oldkeys)) { return(result); } foreach (var keyinfo in oldkeys.ToArray()) { var recvhashi = I2PHMACMD5Digest.Generate(macdata, keyinfo.Key, MACBuf); var oki = header.MAC.Equals(recvhashi); Logging.LogTransport($"SSU {this}: " + $"Old key from {keyinfo.Created} {keyinfo.CreatedDelta, -20} {keyinfo.Type, -10} match: {oki, -6} {keyinfo.Key}"); } return(result); }
/** * 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); }