RC4 Support (DMR, P25p1, P25p2);

This commit is contained in:
lwvmobile 2023-06-11 00:11:55 -04:00
parent 20f0c852aa
commit 8186b62a91
14 changed files with 747 additions and 91 deletions

View File

@ -27,7 +27,7 @@ To scan through a mixture of DMR and P25 Conventional, use:
To scan through NXDN48 only conventional, use:
`dsd-fme -fi -i tcp -C channel_map.csv -Y -U 4532 -N 2> log.ans`
To scan through NXDN98 only conventional, use:
To scan through NXDN96 only conventional, use:
`dsd-fme -fn -i tcp -C channel_map.csv -Y -U 4532 -N 2> log.ans`
The Channel Map setup will be identical to any of the channel maps found for trunking systems, channel numbers do not matter and can be arbitrarily organized, and frequencies can be duplicated to be 'scanned' more frequently in larger CSV files. Scan speed by default is 1 second, and is most stable at that speed. This can be adjusted by using the `-t 2` option, for example, to specify 2 seconds of hang time per frequency. ~~If activity occurs on a frequency, an additional 2 seconds of 'hangtime' will occur on that frequency for any follow up voice activity.~~
@ -165,7 +165,8 @@ c - toggle compact mode
h - toggle call history
z - toggle console payloads
a - toggle call alert beep
4 - force privacy key assertion over fid and svc bits
4 - force privacy/scrambler key assertion over enc identifiers (dmr and nxdn)
6 - force rc4 key assertion over missing pi header/le enc identifiers (dmr)
i - toggle signal inversion on types that can't auto detect (dmr, dpmr)
m - toggle c4fm/qpsk 10/4 (everything but phase 2 signal)
M - toggle c4fm/qpsk 8/3 (phase 2 tdma control channel)

View File

@ -0,0 +1,5 @@
key id(hex), key value (hex) //10-char Hytera BP, RC4
1,1234567890
2,ABCDEF1234
C,0B57935150
64,0B57935150
1 key id(hex), key value (hex) //10-char Hytera BP, RC4
2 1,1234567890
3 2,ABCDEF1234
4 C,0B57935150
5 64,0B57935150

View File

@ -1012,8 +1012,10 @@ uint8_t crc8(uint8_t bits[], unsigned int len);
bool crc8_ok(uint8_t bits[], unsigned int len);
uint8_t crc7(uint8_t bits[], unsigned int len);
//LFSR code courtesy of https://github.com/mattames/LFSR/
//LFSR and LFSRP code courtesy of https://github.com/mattames/LFSR/
void LFSR(dsd_state * state);
void LFSRP(dsd_state * state);
void LFSRN (char * BufferIn, char * BufferOut, dsd_state * state);
void LFSR64(dsd_state * state);
@ -1101,7 +1103,8 @@ unsigned long long int edacs_bch (unsigned long long int message);
int csvGroupImport(dsd_opts * opts, dsd_state * state);
int csvLCNImport(dsd_opts * opts, dsd_state * state);
int csvChanImport(dsd_opts * opts, dsd_state * state);
int csvKeyImport(dsd_opts * opts, dsd_state * state);
int csvKeyImportDec(dsd_opts * opts, dsd_state * state);
int csvKeyImportHex(dsd_opts * opts, dsd_state * state);
#ifdef __cplusplus
extern "C" {

View File

@ -521,13 +521,27 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
if (state->K1 != 0 && fid == 0x68 && so & 0x40)
{
fprintf (stderr, "\n");
if (state->K2 != 0) fprintf (stderr, "\n ");
fprintf (stderr, "%s", KYEL);
fprintf (stderr, " Key %010llX ", state->K1);
fprintf (stderr, "Key %010llX ", state->K1);
if (state->K2 != 0) fprintf (stderr, "%016llX ", state->K2);
if (state->K4 != 0) fprintf (stderr, "%016llX %016llX", state->K3, state->K4);
fprintf (stderr, "%s ", KNRM);
}
}
if (slot == 0 && state->payload_algid == 0x21 && state->R != 0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "Key %010llX ", state->R);
fprintf (stderr, "%s ", KNRM);
}
if (slot == 1 && state->payload_algidR == 0x21 && state->RR != 0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "Key %010llX ", state->RR);
fprintf (stderr, "%s ", KNRM);
}
}

View File

@ -13,6 +13,23 @@ void dmr_late_entry_mi_fragment (dsd_opts * opts, dsd_state * state, uint8_t vc,
{
uint8_t slot = state->currentslot;
//enforce RC4 due to missing PI header, but with valid SVC Opts
//ideally, this would be handled by VC-F single burst, but its not fully reliable compared to this
//due to multiple signalling occurring inside of it, depending on system type
if (state->M == 0x21)
{
if (slot == 0 && state->dmr_so & 0x40)
{
state->payload_algid = 0x21;
state->payload_keyid = 0xFF;
}
if (slot == 1 && state->dmr_soR & 0x40)
{
state->payload_algidR = 0x21;
state->payload_keyidR = 0xFF;
}
}
//collect our fragments and place them into storage
state->late_entry_mi_fragment[slot][vc][0] = (uint64_t)ConvertBitIntoBytes(&ambe_fr[3][0], 4);

View File

@ -146,7 +146,8 @@ int csvChanImport(dsd_opts * opts, dsd_state * state) //channel map import
return 0;
}
int csvKeyImport(dsd_opts * opts, dsd_state * state) //multi-key support
//Decimal Variant of Key Import
int csvKeyImportDec(dsd_opts * opts, dsd_state * state) //multi-key support
{
char filename[1024] = "filename.csv";
sprintf (filename, "%s", opts->key_in_file);
@ -210,3 +211,48 @@ int csvKeyImport(dsd_opts * opts, dsd_state * state) //multi-key support
fclose(fp);
return 0;
}
//Hex Variant of Key Import
int csvKeyImportHex(dsd_opts * opts, dsd_state * state) //key import for rc4 keys
{
char filename[1024] = "filename.csv";
sprintf (filename, "%s", opts->key_in_file);
char buffer[BSIZE];
FILE * fp;
fp = fopen(filename, "r");
if (fp == NULL) {
printf("Unable to open file '%s'\n", filename);
exit(1);
}
int row_count = 0;
int field_count = 0;
unsigned long long int keynumber;
while (fgets(buffer, BSIZE, fp)) {
field_count = 0;
row_count++;
if (row_count == 1)
continue; //don't want labels
char * field = strtok(buffer, ","); //seperate by comma
while (field) {
if (field_count == 0)
{
sscanf (field, "%llX", &keynumber);
}
if (field_count == 1)
{
sscanf (field, "%llX", &state->rkey_array[keynumber]);
}
field = strtok(NULL, ",");
field_count++;
}
fprintf (stderr, "Key [%04llX] [%016llX]", keynumber, state->rkey_array[keynumber]);
fprintf (stderr, "\n");
}
fclose(fp);
return 0;
}

View File

@ -374,7 +374,8 @@ noCarrier (dsd_opts * opts, dsd_state * state)
//unload keys when using keylaoder
if (state->keyloader == 1)
{
state->R = 0; //NXDN
state->R = 0; //NXDN, or RC4 (slot 1)
state->RR = 0; //RC4 (slot 2)
state->K = 0; //BP
state->K1 = 0; //tera 10 char BP
state->H = 0; //shim for above
@ -1090,7 +1091,6 @@ usage ()
printf (" -f1 Decode only P25 Phase 1\n");
printf (" -f2 Decode only P25 Phase 2 (6000 sps) **\n");
printf (" -fd Decode only D-STAR\n");
printf (" -fr Decode only DMR Mono - Single Slot Voice\n");
printf (" -fx Decode only X2-TDMA\n");
printf (" -fi Decode only NXDN48* (6.25 kHz) / IDAS*\n");
printf (" -fn Decode only NXDN96* (12.5 kHz)\n");
@ -1130,9 +1130,10 @@ usage ()
printf (" -F Relax NXDN SACCH/FACCH/CAC/F2U CRC Pass/Fail\n");
printf (" Not recommended on NXDN, but can be bypassed if desired.\n");
printf ("\n");
printf (" -K <dec> Manually Enter Basic Privacy Key (Decimal Value of Key Number)\n");
printf (" -b <dec> Manually Enter Basic Privacy Key (Decimal Value of Key Number)\n");
printf (" (NOTE: This used to be the 'K' option! \n");
printf ("\n");
printf (" -H <hex> Manually Enter **tera 10/32/64 Char Privacy Hex Key (see example below)\n");
printf (" -H <hex> Manually Enter **tera 10/32/64 Char Basic Privacy Hex Key (see example below)\n");
printf (" Encapulate in Single Quotation Marks; Space every 16 chars.\n");
printf (" -H 0B57935150 \n");
printf (" -H '736B9A9C5645288B 243AD5CB8701EF8A' \n");
@ -1140,11 +1141,18 @@ usage ()
printf ("\n");
printf (" -R <dec> Manually Enter dPMR or NXDN EHR Scrambler Key Value (Decimal Value)\n");
printf (" \n");
printf (" -k <file> Import Key List from csv file.\n");
printf (" Only supports NXDN, DMR Basic Privacy and **tera 10-Char (decimal value). \n");
printf (" -1 Manually Enter RC4 Key Value (DMR, P25) (Hex Value) \n");
printf (" \n");
printf (" -k <file> Import Key List from csv file (Decimal Format) -- Lower Case 'k'.\n");
printf (" Only supports NXDN, DMR Basic Privacy (decimal value). \n");
printf (" (dPMR and **tera 32/64 char not supported, DMR uses TG value as key id -- EXPERIMENTAL!!). \n");
printf (" \n");
printf (" -4 Force Privacy Key over FID and SVC bits \n");
printf (" -K <file> Import Key List from csv file (Hexidecimal Format) -- Capital 'K'.\n");
printf (" Use for Hex Value **tera 10-char BP keys and RC4 10-Char Hex Keys. \n");
printf (" \n");
printf (" -4 Force Privacy Key over Encryption Identifiers (DMR BP and NXDN Scrambler) \n");
printf (" \n");
printf (" -6 Force RC4 Key over Missing PI header/LE Encryption Identifiers (DMR) \n");
printf ("\n");
printf (" Trunking Options:\n");
printf (" -C <file> Import Channel to Frequency Map (channum, freq) from csv file. (Capital C) \n");
@ -1158,7 +1166,6 @@ usage ()
printf (" -W Use Imported Group List as a Trunking Allow/White List -- Only Tune with Mode A\n");
printf (" -p Disable Tune to Private Calls (DMR TIII, P25, NXDN Type-C and Type-D)\n");
printf (" -E Disable Tune to Group Calls (DMR TIII, Con+, Cap+, P25, NXDN Type-C, and Type-D)\n");
printf (" (NOTE: NXDN and EDACS, simply disable trunking if desired) \n");
printf (" -e Enable Tune to Data Calls (DMR TIII, Cap+, NXDN Type-C)\n");
printf (" (NOTE: No Clear Distinction between Cap+ Private Voice Calls and Data Calls -- Both enabled with Data Calls \n");
printf (" (NOTE: P25 Data Channels Not Enabled (no handling) \n");
@ -1371,7 +1378,7 @@ main (int argc, char **argv)
exitflag = 0;
while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:YK:H:X:NQ:WrlZTF01:2:345:6:7:89:Ek:")) != -1)
while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:YK:b:H:X:NQ:WrlZTF01:2:345:6:7:89:Ek:")) != -1)
{
opterr = 0;
switch (c)
@ -1384,21 +1391,46 @@ main (int argc, char **argv)
opts.call_alert = 1;
break;
//Free'd up switches include: I, b, J, j, n, O, v, y
//all numberals can be reclaimed, except for -4
//Free'd up switches include: I, J, j, n, O, v, y
//all numerals have reclaimed, except for 4 and 0,1 (rc4 enforcement and single key)
//make sure to put a colon : after each if they need an argument
//or remove colon if no argument required
//NOTE: The 'K' option for single BP key has been swapped to 'b'
//'K' is now used for hexidecimal key.csv imports
//rc4 enforcement on DMR (due to missing the PI header)
case '0':
state.M = 0x21;
fprintf (stderr,"Force RC4 Key over Missing PI header/LE Encryption Identifiers (DMR)\n");
break;
//load single rc4 key
case '1':
sscanf (optarg, "%llX", &state.R);
state.RR = state.R; //put key on both sides
fprintf (stderr, "RC4 Encryption Key Value set to 0x%llX \n", state.R);
opts.unmute_encrypted_p25 = 0;
state.keyloader = 0; //turn off keyloader
break;
case 'Y': //conventional scanner mode
opts.scanner_mode = 1; //enable scanner
opts.p25_trunk = 0; //turn off trunking mode if user enabled it
break;
case 'k': //multi-key loader
case 'k': //multi-key loader (dec)
strncpy(opts.key_in_file, optarg, 1023);
opts.key_in_file[1023] = '\0';
csvKeyImport(&opts, &state);
csvKeyImportDec(&opts, &state);
state.keyloader = 1;
break;
case 'K': //multi-key loader (hex)
strncpy(opts.key_in_file, optarg, 1023);
opts.key_in_file[1023] = '\0';
csvKeyImportHex(&opts, &state);
state.keyloader = 1;
break;
@ -1465,28 +1497,23 @@ main (int argc, char **argv)
break;
case 'C': //new letter assignment for Channel import, flow down to allow temp numbers
case '1': //LCN to Frequency CSV Import <--> flow down to chanimport now, tell users to use a channel map for edacs
case '7': //Channel Map Frequency CSV Import
strncpy(opts.chan_in_file, optarg, 1023);
opts.chan_in_file[1023] = '\0';
csvChanImport (&opts, &state);
break;
case 'G': //new letter assignment for group import, flow down to allow temp numbers
case '2': //Group CSV Import
strncpy(opts.group_in_file, optarg, 1023);
opts.group_in_file[1023] = '\0';
csvGroupImport(&opts, &state);
break;
case 'T': //new letter assignment for trunking, flow down to allow temp numbers
case '3':
opts.p25_trunk = 1;
opts.scanner_mode = 0; //turn off scanner mode if user enabled it
break;
case 'U': //New letter assignment for RIGCTL TCP port, flow down to allow temp numbers
case '5': //RIGCTL TCP port
sscanf (optarg, "%d", &opts.rigctlportno);
if (opts.rigctlportno != 0) opts.use_rigctl = 1;
break;
@ -1496,19 +1523,16 @@ main (int argc, char **argv)
//may change to a different return on sync times and this will matter!
case 't': //New letter assignment for Trunk Hangtime, flow down to allow temp numbers
case '6': //hangtime in seconds, default is 1;
sscanf (optarg, "%f", &opts.trunk_hangtime); //updated for float/decimal values
fprintf (stderr, "Trunking or Fast Scanner Hang Time set to: %.02f sec\n", opts.trunk_hangtime);
break;
case 'q': //New letter assignment for Reverse Mute, flow down to allow temp numbers
case '8':
opts.reverse_mute = 1;
fprintf (stderr, "Reverse Mute\n");
break;
case 'B': //New letter assignment for RIGCTL SetMod BW, flow down to allow temp numbers
case '9': //rigctl setmod bandwidth;
sscanf (optarg, "%d", &opts.setmod_bw);
if (opts.setmod_bw > 25000) opts.setmod_bw = 25000; //not too high
break;
@ -1528,7 +1552,7 @@ main (int argc, char **argv)
// state.use_throttle = 1;
// break;
case 'K':
case 'b': //formerly Capital 'K'
sscanf (optarg, "%lld", &state.K);
if (state.K > 256)
{
@ -1572,7 +1596,7 @@ main (int argc, char **argv)
case '4':
state.M = 1;
fprintf (stderr,"Force Privacy Key Priority over FID and SVC bits.\n");
fprintf (stderr,"Force Privacy Key over Encryption Identifiers (DMR BP and NXDN Scrambler) \n");
break;
//manually set Phase 2 TDMA WACN/SYSID/CC
@ -1990,15 +2014,15 @@ main (int argc, char **argv)
opts.mod_qpsk = 0;
opts.mod_gfsk = 0; //
state.rf_mod = 0; //
opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1;
opts.dmr_mono = 1;
opts.dmr_stereo = 0;
opts.pulse_digi_rate_out = 24000;
opts.pulse_digi_out_channels = 2;
opts.dmr_mono = 0;
opts.dmr_stereo = 1;
state.dmr_stereo = 0; //0
// opts.setmod_bw = 7000;
sprintf (opts.output_name, "DMR Mono");
fprintf(stderr, "Notice: DMR cannot autodetect polarity. \n Use -xr option if Inverted Signal expected.\n");
fprintf (stderr,"Decoding only DMR Mono. \nUsing DMR Stereo '-fs' or XDMA '-ft' is highly encouraged.\n");
sprintf (opts.output_name, "DMR Stereo");
fprintf (stderr,"-fr / DMR Mono switch has been deprecated.\n");
fprintf (stderr,"Decoding DMR Stereo BS/MS Simplex\n");
}
else if (optarg[0] == 'm')

View File

@ -17,6 +17,56 @@
#include "dsd.h"
//test for potential clashing with other key loading mechanisms (bp key loading on tgid, nxdn key loading, etc)
void keyring(dsd_opts * opts, dsd_state * state)
{
//keys now loaded from csv files with the -K key.csv file (capital K)
if (state->currentslot == 0)
state->R = state->rkey_array[state->payload_keyid];
if (state->currentslot == 1)
state->RR = state->rkey_array[state->payload_keyidR];
}
void RC4(int drop, uint8_t keylength, uint8_t messagelength, uint8_t key[], uint8_t cipher[], uint8_t plain[])
{
int i, j, count;
uint8_t t, b;
//init Sbox
uint8_t S[256];
for(int i = 0; i < 256; i++) S[i] = i;
//Key Scheduling
j = 0;
for(i = 0; i < 256; i++)
{
j = (j + S[i] + key[i % keylength]) % 256;
t = S[i];
S[i] = S[j];
S[j] = t;
}
//Drop Bytes and Cipher Byte XOR
i = j = 0;
for(count = 0; count < (messagelength + drop); count++)
{
i = (i + 1) % 256;
j = (j + S[i]) % 256;
t = S[i];
S[i] = S[j];
S[j] = t;
b = S[(S[i] + S[j]) % 256];
//return mbe payload byte here
if (count >= drop)
plain[count - drop] = b^cipher[count - drop];
}
}
int Pr[256] = {
0x0000, 0x1F00, 0xE300, 0xFC00, 0x2503, 0x3A03, 0xC603, 0xD903,
0x4A05, 0x5505, 0xA905, 0xB605, 0x6F06, 0x7006, 0x8C06, 0x9306,
@ -140,6 +190,13 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
unsigned long long int k;
int x;
//these conditions should ensure no clashing with the BP/HBP/Scrambler key loading machanisms already coded in
if (state->currentslot == 0 && state->payload_algid != 0 && state->payload_algid != 0x80 && state->payload_keyid != 0 && state->keyloader == 1)
keyring (opts, state);
if (state->currentslot == 1 && state->payload_algidR != 0 && state->payload_algidR != 0x80 && state->payload_keyidR != 0 && state->keyloader == 1)
keyring (opts, state);
//24-bit TG to 16-bit hash
uint32_t hash = 0;
uint8_t hash_bits[24];
@ -192,7 +249,73 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
mbe_demodulateImbe7200x4400Data (imbe_fr);
state->errs2 = mbe_eccImbe7200x4400Data (imbe_fr, imbe_d);
//P25p1 RC4 Handling
if (state->payload_algid == 0xAA && state->R != 0)
{
uint8_t cipher[11] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t plain[11] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
0x00, 0x00, 0x00, 0x00, 0x00, // <- MI
0x00, 0x00, 0x00}; // <- MI cont.
//easier to manually load up rather than make a loop
rckey[0] = ((state->R & 0xFF00000000) >> 32);
rckey[1] = ((state->R & 0xFF000000) >> 24);
rckey[2] = ((state->R & 0xFF0000) >> 16);
rckey[3] = ((state->R & 0xFF00) >> 8);
rckey[4] = ((state->R & 0xFF) >> 0);
// load valid MI from state->payload_miP
rckey[5] = ((state->payload_miP & 0xFF00000000000000) >> 56);
rckey[6] = ((state->payload_miP & 0xFF000000000000) >> 48);
rckey[7] = ((state->payload_miP & 0xFF0000000000) >> 40);
rckey[8] = ((state->payload_miP & 0xFF00000000) >> 32);
rckey[9] = ((state->payload_miP & 0xFF000000) >> 24);
rckey[10] = ((state->payload_miP & 0xFF0000) >> 16);
rckey[11] = ((state->payload_miP & 0xFF00) >> 8);
rckey[12] = ((state->payload_miP & 0xFF) >> 0);
// if (state->p25vc == 0)
// {
// fprintf (stderr, "%s", KYEL);
// fprintf (stderr, "\n RC4K ");
// for (short o = 0; o < 13; o++)
// {
// fprintf (stderr, "%02X", rckey[o]);
// }
// fprintf (stderr, "%s", KNRM);
// }
//load imbe_d into imbe_cipher octets
int z = 0;
for (i = 0; i < 11; i++)
{
cipher[i] = 0;
plain[i] = 0;
for (short int j = 0; j < 8; j++)
{
cipher[i] = cipher[i] << 1;
cipher[i] = cipher[i] + imbe_d[z];
imbe_d[z] = 0;
z++;
}
}
RC4(state->dropL, 13, 11, rckey, cipher, plain);
state->dropL += 11;
z = 0;
for (short p = 0; p < 11; p++)
{
for (short o = 0; o < 8; o++)
{
imbe_d[z] = (plain[p] & 0x80) >> 7;
plain[p] = plain[p] << 1;
z++;
}
}
}
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
@ -299,8 +422,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
//EXPERIMENTAL!!
//load basic privacy key number from array by the tg value (if not forced)
//currently only Moto BP and Hytera 10 Char BP (converted to decimal)
if (state->M == 0)
//currently only Moto BP and Hytera 10 Char BP
if (state->M == 0 && state->payload_algid == 0)
{
//see if we need to hash a value larger than 16-bits
hash = state->lasttg & 0xFFFFFF;
@ -400,6 +523,155 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
state->DMRvcL++;
}
//DMR RC4, Slot 1
if (state->currentslot == 0 && state->payload_algid == 0x21 && state->R != 0)
{
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t rckey[9] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
0x00, 0x00, 0x00, 0x00}; // <- MI
//easier to manually load up rather than make a loop
rckey[0] = ((state->R & 0xFF00000000) >> 32);
rckey[1] = ((state->R & 0xFF000000) >> 24);
rckey[2] = ((state->R & 0xFF0000) >> 16);
rckey[3] = ((state->R & 0xFF00) >> 8);
rckey[4] = ((state->R & 0xFF) >> 0);
rckey[5] = ((state->payload_mi & 0xFF000000) >> 24);
rckey[6] = ((state->payload_mi & 0xFF0000) >> 16);
rckey[7] = ((state->payload_mi & 0xFF00) >> 8);
rckey[8] = ((state->payload_mi & 0xFF) >> 0);
// if (opts->payload == 1)
// {
// fprintf (stderr, "%s", KYEL);
// fprintf (stderr, " RC4K ");
// for (short o = 0; o < 9; o++)
// {
// fprintf (stderr, "%02X", rckey[o]);
// }
// fprintf (stderr, "%s", KNRM);
// fprintf (stderr, "\n");
// }
short k = 0;
for (short o = 0; o < 7; o++)
{
short b = 0;
for (short p = 0; p < 8; p++)
{
b = b << 1;
b = b + ambe_d[k];
k++;
if (k == 49)
{
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
break;
}
}
cipher[o] = b;
}
RC4(state->dropL, 9, 7, rckey, cipher, plain);
state->dropL += 7;
short z = 0;
for (short p = 0; p < 6; p++)
{
//convert bytes back to bits and load into ambe_d array.
short b = 0; //reset b to use again
for (short o = 0; o < 8; o++)
{
b = (( (plain[p] << o) & 0x80) >> 7);
ambe_d[z] = b;
z++;
if (z == 49)
{
ambe_d[48] = ( (plain[p] << o) & 0x80);
break;
}
}
}
}
//P25p2 RC4 Handling, VCH 0
if (state->currentslot == 0 && state->payload_algid == 0xAA && state->R != 0 && ((state->synctype == 35) || (state->synctype == 36)))
{
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
0x00, 0x00, 0x00, 0x00, 0x00, // <- MI
0x00, 0x00, 0x00}; // <- MI cont.
//easier to manually load up rather than make a loop
rckey[0] = ((state->R & 0xFF00000000) >> 32);
rckey[1] = ((state->R & 0xFF000000) >> 24);
rckey[2] = ((state->R & 0xFF0000) >> 16);
rckey[3] = ((state->R & 0xFF00) >> 8);
rckey[4] = ((state->R & 0xFF) >> 0);
// load valid MI from state->payload_miP
rckey[5] = ((state->payload_miP & 0xFF00000000000000) >> 56);
rckey[6] = ((state->payload_miP & 0xFF000000000000) >> 48);
rckey[7] = ((state->payload_miP & 0xFF0000000000) >> 40);
rckey[8] = ((state->payload_miP & 0xFF00000000) >> 32);
rckey[9] = ((state->payload_miP & 0xFF000000) >> 24);
rckey[10] = ((state->payload_miP & 0xFF0000) >> 16);
rckey[11] = ((state->payload_miP & 0xFF00) >> 8);
rckey[12] = ((state->payload_miP & 0xFF) >> 0);
// if (opts->payload == 1)
// {
// fprintf (stderr, "%s", KYEL);
// fprintf (stderr, " RC4K ");
// for (short o = 0; o < 13; o++)
// {
// fprintf (stderr, "%02X", rckey[o]);
// }
// fprintf (stderr, "%s", KNRM);
// fprintf (stderr, "\n");
// }
short k = 0;
for (short o = 0; o < 7; o++)
{
short b = 0;
for (short p = 0; p < 8; p++)
{
b = b << 1;
b = b + ambe_d[k];
k++;
if (k == 49)
{
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
break;
}
}
cipher[o] = b;
}
RC4(state->dropL, 13, 7, rckey, cipher, plain);
state->dropL += 7;
short z = 0;
for (short p = 0; p < 6; p++)
{
//convert bytes back to bits and load into ambe_d array.
short b = 0; //reset b to use again
for (short o = 0; o < 8; o++)
{
b = (( (plain[p] << o) & 0x80) >> 7);
ambe_d[z] = b;
z++;
if (z == 49)
{
ambe_d[48] = ( (plain[p] << o) & 0x80);
break;
}
}
}
}
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
@ -429,8 +701,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
//EXPERIMENTAL!!
//load basic privacy key number from array by the tg value (if not forced)
//currently only Moto BP and Hytera 10 Char BP (converted to decimal)
if (state->M == 0)
//currently only Moto BP and Hytera 10 Char BP
if (state->M == 0 && state->payload_algidR == 0)
{
//see if we need to hash a value larger than 16-bits
hash = state->lasttgR & 0xFFFFFF;
@ -530,6 +802,155 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
state->DMRvcR++;
}
//DMR RC4, Slot 2
if (state->currentslot == 1 && state->payload_algidR == 0x21 && state->RR != 0)
{
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t rckey[9] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
0x00, 0x00, 0x00, 0x00}; // <- MI
//easier to manually load up rather than make a loop
rckey[0] = ((state->RR & 0xFF00000000) >> 32);
rckey[1] = ((state->RR & 0xFF000000) >> 24);
rckey[2] = ((state->RR & 0xFF0000) >> 16);
rckey[3] = ((state->RR & 0xFF00) >> 8);
rckey[4] = ((state->RR & 0xFF) >> 0);
rckey[5] = ((state->payload_miR & 0xFF000000) >> 24);
rckey[6] = ((state->payload_miR & 0xFF0000) >> 16);
rckey[7] = ((state->payload_miR & 0xFF00) >> 8);
rckey[8] = ((state->payload_miR & 0xFF) >> 0);
// if (opts->payload == 1)
// {
// fprintf (stderr, "%s", KYEL);
// fprintf (stderr, " RC4K ");
// for (short o = 0; o < 9; o++)
// {
// fprintf (stderr, "%02X", rckey[o]);
// }
// fprintf (stderr, "%s", KNRM);
// fprintf (stderr, "\n");
// }
short k = 0;
for (short o = 0; o < 7; o++)
{
short b = 0;
for (short p = 0; p < 8; p++)
{
b = b << 1;
b = b + ambe_d[k];
k++;
if (k == 49)
{
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
break;
}
}
cipher[o] = b;
}
RC4(state->dropR, 9, 7, rckey, cipher, plain);
state->dropR += 7;
short z = 0;
for (short p = 0; p < 6; p++)
{
//convert bytes back to bits and load into ambe_d array.
short b = 0; //reset b to use again
for (short o = 0; o < 8; o++)
{
b = (( (plain[p] << o) & 0x80) >> 7);
ambe_d[z] = b;
z++;
if (z == 49)
{
ambe_d[48] = ( (plain[p] << o) & 0x80);
break;
}
}
}
}
//P25p2 RC4 Handling, VCH 1
if (state->currentslot == 1 && state->payload_algidR == 0xAA && state->RR != 0 && ((state->synctype == 35) || (state->synctype == 36)))
{
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
0x00, 0x00, 0x00, 0x00, 0x00, // <- MI
0x00, 0x00, 0x00}; // <- MI cont.
//easier to manually load up rather than make a loop
rckey[0] = ((state->RR & 0xFF00000000) >> 32);
rckey[1] = ((state->RR & 0xFF000000) >> 24);
rckey[2] = ((state->RR & 0xFF0000) >> 16);
rckey[3] = ((state->RR & 0xFF00) >> 8);
rckey[4] = ((state->RR & 0xFF) >> 0);
//state->payload_miN for VCH1/slot 2
rckey[5] = ((state->payload_miN & 0xFF00000000000000) >> 56);
rckey[6] = ((state->payload_miN & 0xFF000000000000) >> 48);
rckey[7] = ((state->payload_miN & 0xFF0000000000) >> 40);
rckey[8] = ((state->payload_miN & 0xFF00000000) >> 32);
rckey[9] = ((state->payload_miN & 0xFF000000) >> 24);
rckey[10] = ((state->payload_miN & 0xFF0000) >> 16);
rckey[11] = ((state->payload_miN & 0xFF00) >> 8);
rckey[12] = ((state->payload_miN & 0xFF) >> 0);
// if (opts->payload == 1)
// {
// fprintf (stderr, "%s", KYEL);
// fprintf (stderr, " RC4K ");
// for (short o = 0; o < 13; o++)
// {
// fprintf (stderr, "%02X", rckey[o]);
// }
// fprintf (stderr, "%s", KNRM);
// fprintf (stderr, "\n");
// }
short k = 0;
for (short o = 0; o < 7; o++)
{
short b = 0;
for (short p = 0; p < 8; p++)
{
b = b << 1;
b = b + ambe_d[k];
k++;
if (k == 49)
{
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
break;
}
}
cipher[o] = b;
}
RC4(state->dropR, 13, 7, rckey, cipher, plain);
state->dropR += 7;
short z = 0;
for (short p = 0; p < 6; p++)
{
//convert bytes back to bits and load into ambe_d array.
short b = 0; //reset b to use again
for (short o = 0; o < 8; o++)
{
b = (( (plain[p] << o) & 0x80) >> 7);
ambe_d[z] = b;
z++;
if (z == 49)
{
ambe_d[48] = ( (plain[p] << o) & 0x80);
break;
}
}
}
}
mbe_processAmbe2450Dataf (state->audio_out_temp_bufR, &state->errsR, &state->errs2R, state->err_strR,
ambe_d, state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2, opts->uvquality);
@ -584,7 +1005,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
}
else state->dmr_encL = 0;
//second checkdown for P25-2 WACN, SYSID, and CC set
//check for available R key
if (state->R != 0) state->dmr_encL = 0;
//second checkdown for P25p2 WACN, SYSID, and CC set
if (state->synctype == 35 || state->synctype == 36)
{
if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0)
@ -651,7 +1075,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
}
else state->dmr_encR = 0;
//second checkdown for P25-2 WACN, SYSID, and CC set
//check for available RR key
if (state->RR != 0) state->dmr_encR = 0;
//second checkdown for P25p2 WACN, SYSID, and CC set
if (state->synctype == 35 || state->synctype == 36)
{
if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0)

View File

@ -332,15 +332,15 @@ char *choices[] = {
"Decode Legacy Auto**",
"Decode XDMA (P25 and DMR BS/MS)",
"Decode D-STAR*",
"Decode P25-P1*",
"Decode P25p1*",
"Decode EDACS/PV",
"Decode DMR Mono*",
"Decode P25p2 ",
"Decode dPMR",
"Decode NXDN48",
"Decode NXDN96",
"Decode DMR Stereo", //was X2-TDMA*
"Toggle Signal Inversion",
"Privacy Key Entry",
"Key Entry",
"Reset Call History",
"Toggle Payloads to Console",
"Manually Set P2 Parameters", //16
@ -1091,15 +1091,18 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
state->payload_keyid = 0;
state->payload_keyidR = 0;
short int option = 0;
entry_win = newwin(11, WIDTH+6, starty+10, startx+10);
entry_win = newwin(14, WIDTH+6, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, "Key Type Selection");
mvwprintw(entry_win, 3, 2, " ");
mvwprintw(entry_win, 4, 2, "1 - Basic Privacy ");
mvwprintw(entry_win, 5, 2, "2 - **tera Privacy ");
mvwprintw(entry_win, 6, 2, "3 - NXDN/dPMR Scrambler ");
mvwprintw(entry_win, 7, 2, "4 - Force Key Priority ");
mvwprintw(entry_win, 8, 3, " ");
mvwprintw(entry_win, 7, 2, "4 - Force BP/Scr Key Priority ");
mvwprintw(entry_win, 8, 3, "-------------------------------- ");
mvwprintw(entry_win, 9, 2, "5 - RC4 Key ");
mvwprintw(entry_win, 10, 2, "6 - Force DMR RC4 Priority/LE ");
mvwprintw(entry_win, 11, 3, " ");
echo();
refresh();
wscanw(entry_win, "%hd", &option); //%d
@ -1111,16 +1114,15 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
state->K = 0;
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, "DMRA Privacy Key Number (DEC):");
mvwprintw(entry_win, 2, 2, "Basic Privacy Key Number (DEC):");
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
wscanw(entry_win, "%lld", &state->K);
noecho();
if (state->K > 255)
{
state->K = 255;
}
if (state->K > 255) state->K = 255;
state->keyloader = 0; //turn off keyloader
}
if (option == 2)
{
@ -1171,6 +1173,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
wscanw(entry_win, "%llX", &state->K4);
noecho();
state->keyloader = 0; //turn off keyloader
}
if (option == 3)
{
@ -1183,20 +1186,49 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
refresh();
wscanw(entry_win, "%lld", &state->R);
noecho();
if (state->K > 0x7FFF)
{
state->K = 0x7FFF;
}
if (state->R > 0x7FFF) state->R = 0x7FFF;
state->keyloader = 0; //turn off keyloader
}
//toggle enforcement of privacy key over enc bit set on traffic
//toggle enforcement of basic privacy key over enc bit set on traffic
if (option == 4)
{
if (state->M == 0)
if (state->M == 1 || state->M == 0x21)
{
state->M = 1;
state->M = 0;
}
else state->M = 0;
else state->M = 1;
}
if (option == 5)
{
state->R = 0;
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, "RC4 Key Value (HEX):");
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
wscanw(entry_win, "%llX", &state->R);
noecho();
if (state->R > 0xFFFFFFFFFF)
{
state->R = 0xFFFFFFFFFF;
}
state->RR = state->R; //assign for both slots
state->keyloader = 0; //turn off keyloader
}
//toggle enforcement of rc4 key over missing pi header/le on DMR
if (option == 6)
{
if (state->M == 1 || state->M == 0x21)
{
state->M = 0;
}
else state->M = 0x21;
}
if (state->K == 0 && state->K1 == 0 && state->K2 == 0 && state->K3 == 0 && state->K4 == 0)
{
opts->dmr_mute_encL = 1;
@ -1309,7 +1341,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
state->rf_mod = 0;
sprintf (opts->output_name, "P25P1");
sprintf (opts->output_name, "P25p1");
opts->dmr_mono = 0;
opts->dmr_stereo = 0; //this value is the end user option
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
@ -1369,24 +1401,22 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
}
if (choice == 7)
{
//set legacy DMR settings
// resetState (state); //use sparingly, seems to cause issue when switching back to other formats
opts->frame_dmr = 1;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
state->rf_mod = 0;
sprintf (opts->output_name, "DMR Mono");
opts->dmr_mono = 1;
opts->dmr_stereo = 0; //this value is the end user option
state->samplesPerSymbol = 8;
state->symbolCenter = 3;
sprintf (opts->output_name, "P25p2");
opts->dmr_mono = 0;
opts->dmr_stereo = 1; //this value is the end user option
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
opts->pulse_digi_rate_out = 48000;
opts->pulse_digi_out_channels = 1;
opts->pulse_digi_rate_out = 24000;
opts->pulse_digi_out_channels = 2;
opts->frame_dmr = 0;
opts->frame_dstar = 0;
opts->frame_x2tdma = 0;
opts->frame_p25p1 = 0;
opts->frame_p25p2 = 1;
opts->frame_nxdn48 = 0;
opts->frame_nxdn96 = 0;
//opts->frame_dmr = 0;
opts->frame_dpmr = 0;
opts->frame_provoice = 0;
opts->frame_ysf = 0;
@ -2163,13 +2193,13 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (i == 2) printw (" 'q' to Quit ");
if (i == 4) printw (" MBElib %s", versionstr);
#ifdef AERO_BUILD
if (i == 5) printw (" %s ", "Aero Win32");
if (i == 5) printw (" %s ", "Aero Build");
if (i == 6) printw (" v2.1 Win32 \n");
#elif ZDEV_BUILD
if (i == 5) printw (" %s ", "zDEV BUILD");
if (i == 5) printw (" %s ", "zDEV Build");
if (i == 6) printw (" %s \n", GIT_TAG);
#else
if (i == 5) printw (" %s ", "MAIN BUILD");
if (i == 5) printw (" %s ", "Main Build");
if (i == 6) printw (" %s \n", GIT_TAG);
#endif
else printw ("\n");
@ -2314,6 +2344,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (state->K1 != 0) printw ("| Forcing Key Priority -- tera BP Key: %016llX \n", state->K1);
if (state->K != 0 && state->K1 != 0) printw ("| Warning! Multiple DMR Key Types Loaded! \n"); //warning may not be required
}
if (state->M == 0x21)
{
if (state->R != 0) printw ("| Forcing Key Priority -- RC4 Key: %010llX \n", state->R);
}
if (opts->scanner_mode == 1)
{
printw ("| Fast Scan Mode Enabled ");
@ -2653,7 +2687,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if(state->dmrburstL == 16 && state->payload_algid > 0 && (state->dmr_so & 0xCF) == 0x40)
{
attron(COLOR_PAIR(1));
printw ("ALG: [0x%02X] KEY: [0x%02X] MI: [0x%08X] ", state->payload_algid, state->payload_keyid, state->payload_mi);
printw ("ALG: 0x%02X KEY: 0x%02X MI: 0x%08X ", state->payload_algid, state->payload_keyid, state->payload_mi);
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(3));
}
@ -2662,7 +2696,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if(state->dmrburstL > 19 && state->payload_algid > 0 && state->payload_algid != 0x80)
{
attron(COLOR_PAIR(1));
printw ("ALG: [0x%02X] KEY: [0x%04X] MI: [0x%016llX] ", state->payload_algid, state->payload_keyid, state->payload_miP);
printw ("ALG: 0x%02X KEY: 0x%04X MI: 0x%016llX ", state->payload_algid, state->payload_keyid, state->payload_miP);
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(3));
}
@ -2670,7 +2704,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (state->payload_algid == 0xAA || state->payload_algid == 0x21)
{
attron(COLOR_PAIR(1));
printw("ADP-RC4");
printw("RC4 ");
if (state->R != 0) { printw("Key: %010llX ", state->R); }
attron(COLOR_PAIR(3));
}
if (state->payload_algid == 0x81 || state->payload_algid == 0x22)
@ -2851,7 +2886,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if(state->dmrburstR == 16 && state->payload_algidR > 0 && (state->dmr_soR & 0xCF) == 0x40)
{
attron(COLOR_PAIR(1));
printw ("ALG: [0x%02X] KEY: [0x%02X] MI: [0x%08X] ", state->payload_algidR, state->payload_keyidR, state->payload_miR);
printw ("ALG: 0x%02X KEY: 0x%02X MI: 0x%08X ", state->payload_algidR, state->payload_keyidR, state->payload_miR);
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(3));
}
@ -2859,14 +2894,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if(state->dmrburstR > 19 && state->payload_algidR > 0 && state->payload_algidR != 0x80)
{
attron(COLOR_PAIR(1));
printw ("ALG: [0x%02X] KEY: [0x%04X] MI: [0x%016llX] ", state->payload_algidR, state->payload_keyidR, state->payload_miN);
printw ("ALG: 0x%02X KEY: 0x%04X MI: 0x%016llX ", state->payload_algidR, state->payload_keyidR, state->payload_miN);
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(3));
}
if (state->payload_algidR == 0xAA || state->payload_algidR == 0x21)
{
attron(COLOR_PAIR(1));
printw("ADP-RC4");
printw("RC4 ");
if (state->RR != 0) { printw("Key: %010llX ", state->RR); }
attron(COLOR_PAIR(3));
}
if (state->payload_algidR == 0x81 || state->payload_algidR == 0x22)
@ -3305,10 +3341,16 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (c == 52) // '4' key, toggle force privacy key over fid and svc (dmr)
{
if (state->M == 1) state->M = 0;
if (state->M == 1 || state->M == 0x21) state->M = 0;
else state->M = 1;
}
if (c == 54) // '6' key, toggle force rc4 key over missing pi header/late entry
{
if (state->M == 1 || state->M == 0x21) state->M = 0;
else state->M = 0x21;
}
if (c == 105) //'i' key, toggle signal inversion on inverted types
{
//Set all signal for inversion or uninversion

View File

@ -459,6 +459,9 @@ processHDU(dsd_opts* opts, dsd_state* state)
mihex2 = (unsigned long long int)ConvertBitIntoBytes(&mi[32], 32);
mihex3 = (unsigned long long int)ConvertBitIntoBytes(&mi[64], 8);
//reset dropbytes - skip first 11 for LCW
state->dropL = 267;
//set vc counter to 0
state->p25vc = 0;
@ -466,10 +469,11 @@ processHDU(dsd_opts* opts, dsd_state* state)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, " HDU ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08llX%08llX%02llX", algidhex, kidhex, mihex1, mihex2, mihex3);
fprintf (stderr, "%s", KNRM);
fprintf (stderr, " HDU ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX%02llX", algidhex, kidhex, mihex1, mihex2, mihex3);
state->payload_algid = algidhex;
state->payload_keyid = kidhex;
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key: %010llX", state->R);
fprintf (stderr, "%s", KNRM);
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3
state->payload_miP = (mihex1 << 32) | (mihex2);

View File

@ -171,6 +171,8 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
// TODO: error correction of the LSD bytes...
// TODO: do something useful with the LSD bytes...
state->dropL += 2; //need to skip 2 here for the LSD bytes
}
// IMBE 9

View File

@ -172,6 +172,8 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
// TODO: error correction of the LSD bytes...
// TODO: do something useful with the LSD bytes...
state->dropL += 2; //need to skip 2 here for the LSD bytes
}
// IMBE 9
@ -183,6 +185,9 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
//set vc counter to 0
state->p25vc = 0;
//reset dropbytes -- skip first 11 for next LCW
state->dropL = 267;
if (opts->errorbars == 1)
{
fprintf (stderr, "\n");
@ -366,11 +371,11 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
if (irrecoverable_errors == 0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%02X MI: 0x%08llX%08llX%02llX", algidhex, kidhex, mihex1, mihex2, mihex3);
fprintf (stderr, "%s", KNRM);
fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX%02llX", algidhex, kidhex, mihex1, mihex2, mihex3);
state->payload_algid = algidhex;
state->payload_keyid = kidhex;
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key: %010llX", state->R);
fprintf (stderr, "%s", KNRM);
//only use 64 MSB, trailing 8 bits aren't used, so no mihex3
state->payload_miP = (mihex1 << 32) | (mihex2);
@ -390,4 +395,45 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "%s", KNRM);
}
//run LFSR on the MI if we have irrecoverable errors here
if (irrecoverable_errors && state->payload_algid != 0x80 && state->payload_keyid != 0 && state->payload_miP != 0)
{
LFSRP(state);
fprintf (stderr, "\n");
}
}
//LFSR code courtesy of https://github.com/mattames/LFSR/
void LFSRP(dsd_state * state)
{
//rework for P2 TDMA support
unsigned long long int lfsr = 0;
if (state->currentslot == 0)
lfsr = state->payload_miP;
if (state->currentslot == 1)
lfsr = state->payload_miN;
int cnt = 0;
for(cnt=0;cnt<64;cnt++)
{
// Polynomial is C(x) = x^64 + x^62 + x^46 + x^38 + x^27 + x^15 + 1
unsigned long long int bit = ((lfsr >> 63) ^ (lfsr >> 61) ^ (lfsr >> 45) ^ (lfsr >> 37) ^ (lfsr >> 26) ^ (lfsr >> 14)) & 0x1;
lfsr = (lfsr << 1) | (bit);
}
if (state->currentslot == 0)
state->payload_miP = lfsr;
if (state->currentslot == 1)
state->payload_miN = lfsr;
//print current ENC identifiers already known and new calculated MI
fprintf (stderr, "%s", KYEL);
if (state->currentslot == 0)
fprintf (stderr, " LDU2/ESS_B FEC ERR - ALG: 0x%02X KEY ID: 0x%04X LFSR MI: 0x%016llX", state->payload_algid, state->payload_keyid, state->payload_miP);
if (state->currentslot == 1)
fprintf (stderr, " LDU2/ESS_B FEC ERR - ALG: 0x%02X KEY ID: 0x%04X LFSR MI: 0x%016llX", state->payload_algidR, state->payload_keyidR, state->payload_miN);
fprintf (stderr, "%s", KNRM);
}

View File

@ -552,6 +552,7 @@ void process_ESS (dsd_opts * opts, dsd_state * state)
fprintf (stderr, " ALG ID 0x%02X", state->payload_algid);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
fprintf (stderr, " MI 0x%016llX", state->payload_miP);
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
fprintf (stderr, " ESSB");
}
@ -567,6 +568,7 @@ void process_ESS (dsd_opts * opts, dsd_state * state)
fprintf (stderr, " ALG ID 0x%02X", state->payload_algidR);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
fprintf (stderr, " MI 0x%016llX", state->payload_miN);
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
fprintf (stderr, " ESSB");
}
@ -574,7 +576,11 @@ void process_ESS (dsd_opts * opts, dsd_state * state)
}
if (ec == -1 || ec >= 15)
{
//ESS R-S Failure
//ESS R-S Failure -- run LFSR on current MI if applicable
if (state->currentslot == 0 && state->payload_algid != 0x80 && state->payload_keyid != 0 && state->payload_miP != 0)
LFSRP(state);
if (state->currentslot == 1 && state->payload_algidR != 0x80 && state->payload_keyidR != 0 && state->payload_miN != 0)
LFSRP(state);
}
fprintf (stderr, "%s", KNRM);
@ -651,6 +657,13 @@ void process_2V (dsd_opts * opts, dsd_state * state)
process_ESS(opts, state);
//reset drop bytes after a 2V
if (state->currentslot == 0 && state->payload_algid == 0xAA)
state->dropL = 256;
if (state->currentslot == 1 && state->payload_algidR == 0xAA)
state->dropR = 256;
}
//P2 Data Unit ID

View File

@ -120,6 +120,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20;
fprintf (stderr, "\n VCH 0 - ");
@ -142,6 +143,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
fprintf (stderr, " MI 0x%016llX", state->payload_miP);
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
fprintf(stderr, " MPTT");
// fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC");
@ -153,6 +155,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0;
state->dropR = 256;
state->payload_algidR = 0; //zero this out as well
state->dmrburstR = 20;
@ -176,6 +179,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
fprintf (stderr, " MI 0x%016llX", state->payload_miN);
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
fprintf(stderr, " MPTT");
// fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC");
@ -194,6 +198,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23;
state->payload_algid = 0;
state->payload_keyid = 0;
@ -217,6 +222,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
state->fourv_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23;
state->payload_algidR = 0;
state->payload_keyidR = 0;
@ -369,6 +375,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20;
fprintf (stderr, "\n VCH 0 - ");
@ -391,6 +398,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
fprintf (stderr, " MI 0x%016llX", state->payload_miP);
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
fprintf(stderr, " MPTT");
// fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC");
@ -402,6 +410,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 20;
fprintf (stderr, "\n VCH 1 - ");
@ -424,6 +433,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR);
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
fprintf (stderr, " MI 0x%016llX", state->payload_miN);
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
fprintf(stderr, " MPTT");
// fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC");
@ -441,6 +451,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
state->fourv_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23;
state->payload_algid = 0; //zero this out as well
state->payload_keyid = 0;
@ -464,6 +475,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
state->fourv_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23;
state->payload_algidR = 0; //zero this out as well
state->payload_keyidR = 0;