From 3abc4aa463cc1baada772a5bd304dfe434758932 Mon Sep 17 00:00:00 2001 From: firealarmss Date: Sun, 9 Mar 2025 01:47:41 -0600 Subject: [PATCH] Initial work to calculate LSFR for future use --- WhackerLinkConsoleV2/ChannelBox.xaml.cs | 1 + WhackerLinkConsoleV2/FneSystemBase.P25.cs | 4 +- WhackerLinkConsoleV2/MainWindow.xaml.cs | 51 +++++++++++------------ WhackerLinkConsoleV2/P25Crypto.cs | 35 ++++++++++++++++ 4 files changed, 62 insertions(+), 29 deletions(-) diff --git a/WhackerLinkConsoleV2/ChannelBox.xaml.cs b/WhackerLinkConsoleV2/ChannelBox.xaml.cs index b57659f..18c9d2d 100644 --- a/WhackerLinkConsoleV2/ChannelBox.xaml.cs +++ b/WhackerLinkConsoleV2/ChannelBox.xaml.cs @@ -57,6 +57,7 @@ namespace WhackerLinkConsoleV2.Controls public int p25N { get; set; } = 0; public int p25SeqNo { get; set; } = 0; + public int p25Errs { get; set; } = 0; public byte[] mi = new byte[P25Defines.P25_MI_LENGTH]; // Message Indicator public byte algId = 0; // Algorithm ID diff --git a/WhackerLinkConsoleV2/FneSystemBase.P25.cs b/WhackerLinkConsoleV2/FneSystemBase.P25.cs index 5bca64f..34eafbb 100644 --- a/WhackerLinkConsoleV2/FneSystemBase.P25.cs +++ b/WhackerLinkConsoleV2/FneSystemBase.P25.cs @@ -453,11 +453,9 @@ namespace WhackerLinkConsoleV2 { DateTime pktTime = DateTime.Now; - if ( e.DUID == P25DUID.TSDU || e.DUID == P25DUID.PDU) + if (e.DUID == P25DUID.HDU || e.DUID == P25DUID.TSDU || e.DUID == P25DUID.PDU) return; - byte control = e.Data[14U]; - if (e.CallType == CallType.GROUP) { if (e.SrcId == 0) diff --git a/WhackerLinkConsoleV2/MainWindow.xaml.cs b/WhackerLinkConsoleV2/MainWindow.xaml.cs index d61b829..529f157 100644 --- a/WhackerLinkConsoleV2/MainWindow.xaml.cs +++ b/WhackerLinkConsoleV2/MainWindow.xaml.cs @@ -48,6 +48,7 @@ using System.Security.Cryptography; using fnecore.P25.LC.TSBK; using WebSocketSharp; using NWaves.Signals; +using static WhackerLinkConsoleV2.P25Crypto; namespace WhackerLinkConsoleV2 { @@ -92,7 +93,7 @@ namespace WhackerLinkConsoleV2 public MainWindow() { -#if DEBUG +#if !DEBUG ConsoleNative.ShowConsole(); #endif InitializeComponent(); @@ -1837,34 +1838,23 @@ namespace WhackerLinkConsoleV2 //Log.Logger.Debug($"Decoding IMBE buffer: {FneUtils.HexDump(imbe)}"); short[] samples = new short[FneSystemBase.MBE_SAMPLES_LENGTH]; - int errs = 0; -#if WIN32 + if (cryptodev) { //Console.WriteLine($"MI: {FneUtils.HexDump(channel.mi)}"); //Console.WriteLine($"Algorithm ID: {channel.algId}"); //Console.WriteLine($"Key ID: {channel.kId}"); - channel.crypter.Process(imbe, frameType, n); } +#if WIN32 if (channel.extFullRateVocoder == null) channel.extFullRateVocoder = new AmbeVocoder(true); - errs = channel.extFullRateVocoder.decode(imbe, out samples); + channel.p25Errs = channel.extFullRateVocoder.decode(imbe, out samples); #else - if (cryptodev) - { - Console.WriteLine($"MI: {FneUtils.HexDump(channel.mi)}"); - Console.WriteLine($"Algorithm ID: {channel.algId}"); - Console.WriteLine($"Key ID: {channel.kId}"); - - channel.crypter.Process(imbe, frameType, n); - } - //Console.WriteLine(FneUtils.HexDump(imbe)); - - errs = channel.decoder.decode(imbe, samples); + channel.p25Errs = channel.decoder.decode(imbe, samples); #endif if (emergency) @@ -2020,7 +2010,7 @@ namespace WhackerLinkConsoleV2 } // Is the call over? - if (((e.DUID == P25DUID.TDU) || (e.DUID == P25DUID.TDULC)) && (slot.RxType != FrameType.TERMINATOR)) + if (((e.DUID == P25DUID.TDU) || (e.DUID == P25DUID.TDULC)) && (slot.RxType != fnecore.FrameType.TERMINATOR)) { channel.IsReceiving = false; TimeSpan callDuration = pktTime - slot.RxStart; @@ -2032,6 +2022,8 @@ namespace WhackerLinkConsoleV2 if ((channel.algId != cpgChannel.GetAlgoId() || channel.kId != cpgChannel.GetKeyId()) && channel.algId != P25Defines.P25_ALGO_UNENCRYPT) continue; + byte[] newMI = new byte[P25Defines.P25_MI_LENGTH]; + int count = 0; switch (e.DUID) @@ -2107,23 +2099,23 @@ namespace WhackerLinkConsoleV2 // The '6D' record - IMBE Voice 12 + Encryption Sync Buffer.BlockCopy(data, count, channel.netLDU2, 50, 17); - channel.mi[0] = data[count + 1]; - channel.mi[1] = data[count + 2]; - channel.mi[2] = data[count + 3]; + newMI[0] = data[count + 1]; + newMI[1] = data[count + 2]; + newMI[2] = data[count + 3]; count += 17; // The '6E' record - IMBE Voice 13 + Encryption Sync Buffer.BlockCopy(data, count, channel.netLDU2, 75, 17); - channel.mi[3] = data[count + 1]; - channel.mi[4] = data[count + 2]; - channel.mi[5] = data[count + 3]; + newMI[3] = data[count + 1]; + newMI[4] = data[count + 2]; + newMI[5] = data[count + 3]; count += 17; // The '6F' record - IMBE Voice 14 + Encryption Sync Buffer.BlockCopy(data, count, channel.netLDU2, 100, 17); - channel.mi[6] = data[count + 1]; - channel.mi[7] = data[count + 2]; - channel.mi[8] = data[count + 3]; + newMI[6] = data[count + 1]; + newMI[7] = data[count + 2]; + newMI[8] = data[count + 3]; count += 17; // The '70' record - IMBE Voice 15 + Encryption Sync @@ -2144,6 +2136,13 @@ namespace WhackerLinkConsoleV2 Buffer.BlockCopy(data, count, channel.netLDU2, 200, 16); count += 16; + if (channel.p25Errs > 0) // temp, need to actually get erros I guess + P25Crypto.CycleP25Lfsr(channel.mi); + else + Array.Copy(newMI, channel.mi, P25Defines.P25_MI_LENGTH); + + Console.WriteLine(channel.p25Errs); + // decode 9 IMBE codewords into PCM samples P25DecodeAudioFrame(channel.netLDU2, e, handler, channel, isEmergency, P25Crypto.FrameType.LDU2); } diff --git a/WhackerLinkConsoleV2/P25Crypto.cs b/WhackerLinkConsoleV2/P25Crypto.cs index e7f2e92..57b4b9a 100644 --- a/WhackerLinkConsoleV2/P25Crypto.cs +++ b/WhackerLinkConsoleV2/P25Crypto.cs @@ -116,6 +116,41 @@ namespace WhackerLinkConsoleV2 return false; } + /// + /// Cycles the P25 LFSR (Linear Feedback Shift Register) based on the given polynomial. + /// + /// The message indicator array to be processed. + public static void CycleP25Lfsr(byte[] MI) + { + if (MI == null || MI.Length < 9) + throw new ArgumentException("MI must be at least 9 bytes long."); + + ulong lfsr = 0; + + // Load the first 8 bytes into the LFSR + for (int i = 0; i < 8; i++) + { + lfsr = (lfsr << 8) | MI[i]; + } + + // Perform 64-bit LFSR cycling using the polynomial: + // C(x) = x^64 + x^62 + x^46 + x^38 + x^27 + x^15 + 1 + for (int cnt = 0; cnt < 64; cnt++) + { + ulong bit = ((lfsr >> 63) ^ (lfsr >> 61) ^ (lfsr >> 45) ^ (lfsr >> 37) ^ (lfsr >> 26) ^ (lfsr >> 14)) & 0x1; + lfsr = (lfsr << 1) | bit; + } + + // Store the result back into MI + for (int i = 7; i >= 0; i--) + { + MI[i] = (byte)(lfsr & 0xFF); + lfsr >>= 8; + } + + MI[8] = 0; // Last byte is always set to zero + } + /// /// Process RC4 ///