diff --git a/examples/cygwin_bat/complete_usage_options.txt b/examples/cygwin_bat/complete_usage_options.txt index 3956b7a..3c4d14f 100644 --- a/examples/cygwin_bat/complete_usage_options.txt +++ b/examples/cygwin_bat/complete_usage_options.txt @@ -1,4 +1,4 @@ -Build Version: AW 2025-173-g21c02ac +Build Version: AW 2025-175-ga5b9984 MBElib Version: 1.3.4 CODEC2 Support Enabled @@ -173,16 +173,18 @@ Advanced Decoder options: -1 Manually Enter RC4 or DES Key Value (DMR, P25, NXDN) (Hex Value) - -2 Manually Enter TYT and Enforce 16-bit BP Key Value (DMR) (Hex Value) + -2 Manually Enter and TYT Enforce 16-bit BP Key Value (DMR) (Hex Value) - -! Manually Enter TYT and Enforce Advanced Privacy (PC4) AP Hex Key (see example below) + -! Manually Enter and Enforce TYT Advanced Privacy (PC4) AP Hex Key (see example below) Encapulate in Single Quotation Marks; Space every 16 chars. -! '736B9A9C5645288B 243AD5CB8701EF8A' - -5 Manually Enter TYT and Enforce Enhanced Privacy (AES-128) EP Hex Key (see example below) + -5 Manually Enter and Enforce TYT Enhanced Privacy (AES-128) EP Hex Key (see example below) Encapulate in Single Quotation Marks; Space every 16 chars. -5 '736B9A9C5645288B 243AD5CB8701EF8A' + -9 Manually Enter and Enforce Kenwood 15-bit Scrambler Key Value (DMR) (Dec Value) + -k Import Key List from csv file (Decimal Format) -- Lower Case 'k'. Only supports NXDN, DMR Basic Privacy (decimal value). (dPMR and Hytera 32/64 char not supported, DMR uses TG value as key id -- EXPERIMENTAL!!). diff --git a/include/dsd.h b/include/dsd.h index 2fc9278..85bea6c 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -992,6 +992,11 @@ typedef struct int tyt_bp; int tyt_ep; + //kenwood scrambler on DMR with forced application + int ken_sc; + uint8_t static_ks_bits[2][882]; + int static_ks_counter[2]; + } dsd_state; /* diff --git a/src/dmr_flco.c b/src/dmr_flco.c index d25254b..d5cdd84 100644 --- a/src/dmr_flco.c +++ b/src/dmr_flco.c @@ -56,6 +56,19 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C target = (uint32_t)ConvertBitIntoBytes(&lc_bits[24], 24); //Target or Talk Group source = (uint32_t)ConvertBitIntoBytes(&lc_bits[48], 24); + //Kenwood w/ Scrambler Application on DMR (disable this if clash with other link control, its obscure) + uint8_t is_kenwood_sc = 1; + if (*IrrecoverableErrors == 0 && CRCCorrect == 1 && pf == 1 && fid == 0x20 && (so & 0x40) == 0x40) + { + pf = 0; //turn off PF flag + fid = 0; //unclear if this signals FID (or is cipher type for scrambler) + + //reset bit counter on static key bit counter (should do this after VC6 instead of relying on this, but meh, obscure cipher type) + state->static_ks_counter[state->currentslot] = 0; + + is_kenwood_sc = 1; + } + //read ahead a little to get this for the xpt flag if (*IrrecoverableErrors == 0 && flco == 0x09 && fid == 0x68) { @@ -295,7 +308,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C //unknown other manufacturer or OTA ENC, etc. //removed tait from the list, added hytera 0x08 - if (fid != 0 && fid != 0x68 && fid != 0x10 && fid != 0x08) + if (fid != 0 && fid != 0x68 && fid != 0x10 && fid != 0x08 && is_kenwood_sc == 0) { if (type == 1) fprintf (stderr, "%s \n", KYEL); if (type == 2) fprintf (stderr, "%s \n", KYEL); @@ -651,6 +664,9 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C state->gi[slot] = 1; } + if (is_kenwood_sc) + fprintf(stderr, "Kenwood Scrambler "); + fprintf(stderr, "Call "); diff --git a/src/dsd_main.c b/src/dsd_main.c index 6ca20ce..44dbaeb 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -607,6 +607,9 @@ memset (state->s_ru, 0, sizeof(state->s_ru)); memset (state->s_l4u, 0, sizeof(state->s_l4u)); memset (state->s_r4u, 0, sizeof(state->s_r4u)); + + //we do reset the counter, but not the static_ks_bits + memset (state->static_ks_counter, 0, sizeof(state->static_ks_counter)); } //nocarrier @@ -1086,6 +1089,8 @@ state->tyt_ap = 0; state->tyt_bp = 0; state->tyt_ep = 0; + + state->ken_sc = 0; //ks array storage and counters memset (state->ks_octetL, 0, sizeof(state->ks_octetL)); @@ -1095,6 +1100,9 @@ state->octet_counter = 0; state->bit_counterL = 0; state->bit_counterR = 0; + + memset (state->static_ks_bits, 0, sizeof(state->static_ks_bits)); + memset (state->static_ks_counter, 0, sizeof(state->static_ks_counter)); //AES Specific Variables memset (state->aes_key, 0, sizeof(state->aes_key)); @@ -1579,16 +1587,18 @@ printf (" \n"); printf (" -1 Manually Enter RC4 or DES Key Value (DMR, P25, NXDN) (Hex Value) \n"); printf (" \n"); - printf (" -2 Manually Enter TYT and Enforce 16-bit BP Key Value (DMR) (Hex Value) \n"); + printf (" -2 Manually Enter and TYT Enforce 16-bit BP Key Value (DMR) (Hex Value) \n"); printf (" \n"); - printf (" -! Manually Enter TYT and Enforce Advanced Privacy (PC4) AP Hex Key (see example below)\n"); + printf (" -! Manually Enter and Enforce TYT Advanced Privacy (PC4) AP Hex Key (see example below)\n"); printf (" Encapulate in Single Quotation Marks; Space every 16 chars.\n"); printf (" -! '736B9A9C5645288B 243AD5CB8701EF8A' \n"); printf (" \n"); - printf (" -5 Manually Enter TYT and Enforce Enhanced Privacy (AES-128) EP Hex Key (see example below)\n"); + printf (" -5 Manually Enter and Enforce TYT Enhanced Privacy (AES-128) EP Hex Key (see example below)\n"); printf (" Encapulate in Single Quotation Marks; Space every 16 chars.\n"); printf (" -5 '736B9A9C5645288B 243AD5CB8701EF8A' \n"); printf (" \n"); + printf (" -9 Manually Enter and Enforce Kenwood 15-bit Scrambler Key Value (DMR) (Dec Value) \n"); + printf (" \n"); printf (" -k 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 Hytera 32/64 char not supported, DMR uses TG value as key id -- EXPERIMENTAL!!). \n"); @@ -1907,7 +1917,7 @@ exitflag = 0; - while ((c = getopt (argc, argv, "~yhaepPqs:t:v:z:i:o:d:c:g:n:w:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:YK:b:H:X:NQ:WrlZTF:!:01:2:345:6:7:89Ek:I:J:O")) != -1) + while ((c = getopt (argc, argv, "~yhaepPqs:t:v:z:i:o:d:c:g:n:w:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:YK:b:H:X:NQ:WrlZTF:!:01:2:345:6:7:89:Ek:I:J:O")) != -1) { switch (c) @@ -1962,12 +1972,6 @@ fprintf (stderr, "TG Hold set to %d \n", state.tg_hold); break; - case '9': //Leaving Enabled to maintain backwards compatability - state.ea_mode = 0; - state.esk_mask = 0; - fprintf (stderr,"Force Enabling EDACS Standard/Networked Mode Mode without ESK.\n"); - break; - //experimental audio monitoring case '8': opts.monitor_input_audio = 1; @@ -2054,9 +2058,35 @@ //load static keystream into ctx.bits since that isn't ever zeroed out for (int i = 0; i < 49; i++) ctx.bits[i] = ks_bits[i]; - fprintf (stderr,"DMR TYT EP (AES-128) Key %016llX %016llX with Forced Application\n", K1, K2); + fprintf (stderr,"DMR TYT EP (AES-128) Key %016llX%016llX with Forced Application\n", K1, K2); state.tyt_ep = 1; break; + + case '9': + /* + SLOT 1 Protected LC FLCO=0x00 FID=0x20 <--this link appears to indicate scrambler usage from Kenwood on DMR + DMR PDU Payload [80][20][40][00][00][01][00][00][01] SB: 00000000000 - 000; + + SLOT 1 TGT=1 SRC=1 FLCO=0x00 FID=0x00 SVC=0x00 Group Call <--same call, but no scrambler on same Kenwood Radio + DMR PDU Payload [00][00][00][00][00][01][00][00][01] + + For This, we could possible transition this to not be enforced + since we may have a positive indicator in link control, + but needs further samples and validation + */ + int lfsr = 0, bit = 0; + sscanf (optarg, "%ld", &lfsr); + fprintf (stderr,"DMR Kenwood 15-bit Scrambler Key %05d with Forced Application\n", lfsr); + for (int i = 0; i < 882; i++) + { + state.static_ks_bits[0][i] = lfsr & 0x1; + state.static_ks_bits[1][i] = lfsr & 0x1; + bit = ( (lfsr >> 1) ^ (lfsr >> 0) ) & 1; + lfsr = ( (lfsr >> 1 ) | (bit << 14) ); + } + + state.ken_sc = 1; + break; case '3': opts.dmr_le = 0; diff --git a/src/dsd_mbe.c b/src/dsd_mbe.c index 1630b68..d303a30 100644 --- a/src/dsd_mbe.c +++ b/src/dsd_mbe.c @@ -832,6 +832,13 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a ambe_d[i] ^= (uint8_t)(ctx.bits[i] & 1); } + //DMR Kenwood Scrambler, Either Slot (static single key'd enforced KS) //should probably break this up, but this is a test for now + if (state->ken_sc == 1) + { + for (int i = 0; i < 49; i++) + ambe_d[i] ^= (uint8_t)(state->static_ks_bits[state->currentslot][(state->static_ks_counter[state->currentslot]++)%882] & 1); //Yikes! + } + //P25p2 RC4 Handling, VCH 0 if (state->currentslot == 0 && state->payload_algid == 0xAA && state->R != 0 && ((state->synctype == 35) || (state->synctype == 36))) { @@ -1267,6 +1274,9 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a } } + if (state->ken_sc == 1) + state->dmr_encL = 0; + //reverse mute testing, only mute unencrypted traffic (slave piggyback dsd+ method) if (opts->reverse_mute == 1) { @@ -1344,6 +1354,9 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a } } + if (state->ken_sc == 1) + state->dmr_encR = 0; + //reverse mute testing, only mute unencrypted traffic (slave piggyback dsd+ method) if (opts->reverse_mute == 1) {