DMR: Reorganize TYT and KEN encrytion modes, putting them into the proper files; #302 #303

This commit is contained in:
lwvmobile
2025-08-19 19:18:01 -04:00
parent 7428a87d80
commit 6f171620dc
4 changed files with 127 additions and 134 deletions

View File

@@ -1622,6 +1622,11 @@ void aes_ctr_bitwise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * paylo
//Tytera Encryption Modes
void tyt16_ambe2_codeword_keystream(dsd_state * state, char ambe_fr[4][24], int fnum);
void tyt_ep_aes_keystream_creation(dsd_state * state, char * input);
void tyt_ap_pc4_keystream_creation(dsd_state * state, char * input);
//Misc Other Encryption Modes
void ken_dmr_scrambler_keystream_creation(dsd_state * state, char * input);
//Hytera Enhanced
void hytera_enhanced_rc4_setup(dsd_opts * opts, dsd_state * state, unsigned long long int key_value, unsigned long long int mi_value);

31
src/crypt-etc.c Normal file
View File

@@ -0,0 +1,31 @@
#include "dsd.h"
void ken_dmr_scrambler_keystream_creation(dsd_state * state, char * input)
{
/*
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 <--different call, no scrambler from 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 (input, "%d", &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;
}

View File

@@ -1,7 +1,8 @@
#include "dsd.h"
#include "dmr_const.h"
#include "pc4.h"
//interleaved code words for AMBE+2
//interleaved code words for AMBE+2 (as it arrives over the air)
void ambe2_codeword_print_i (dsd_opts * opts, char ambe_fr[4][24])
{
uint8_t interleaved[72];
@@ -94,8 +95,8 @@ void ambe2_codeword_print_f (dsd_opts * opts, char ambe_fr[4][24])
}
//tested working perfectly fine on some Tytera BP samples, but not on others
//is there two or more different Tytera (or CCR) BP modes depending on FW?
//NOTE: This mode DOES NOT work over a repeater, simplex only
//repeaters may or will attempt to correct the frame errors
void tyt16_ambe2_codeword_keystream(dsd_state * state, char ambe_fr[4][24], int fnum)
{
@@ -154,4 +155,87 @@ void tyt16_ambe2_codeword_keystream(dsd_state * state, char ambe_fr[4][24], int
z++;
}
}
void tyt_ap_pc4_keystream_creation(dsd_state * state, char * input)
{
unsigned char key1[16] = {0};
unsigned char key2[16] = {0};
char buf[1024];
strncpy(buf, input, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
char *pEnd;
uint64_t K1 = strtoull(buf, &pEnd, 16);
uint64_t K2 = strtoull(pEnd, &pEnd, 16);
u64_to_bytes_be(K1, &key1[0]);
u64_to_bytes_be(K2, &key1[8]);
for (int i=0;i<16;i++) key2[i] = key1[15-i];
/* Create key schedule */
create_keys(&ctx, key2, sizeof(key2));
ctx.rounds = nbround;
fprintf (stderr,"DMR TYT AP (PC4) 128-bit Key %016llX%016llX with Forced Application\n", (unsigned long long int)K1, (unsigned long long int)K2);
state->tyt_ap = 1;
}
void tyt_ep_aes_keystream_creation(dsd_state * state, char * input)
{
char buf[1024];
strncpy(buf, input, 1023);
buf[1023] = '\0';
char *pEnd;
unsigned long long int K1 = strtoull (buf, &pEnd, 16);
unsigned long long int K2 = strtoull (pEnd, &pEnd, 16);
//
uint8_t static_key[32];
memset(static_key, 0, sizeof(static_key));
//static key value
static_key[0]=0x6e; static_key[1]=0x02; static_key[2]=0x8d; static_key[3]=0x8a;
static_key[4]=0xca; static_key[5]=0xeb; static_key[6]=0x9b; static_key[7]=0xbe;
static_key[8]=0x42; static_key[9]=0x72; static_key[10]=0xfb; static_key[11]=0x82;
static_key[12]=0x64; static_key[13]=0x56; static_key[14]=0x31; static_key[15]=0xfa;
//the key value provided by user
uint8_t user_key[16];
memset(user_key, 0, sizeof(user_key));
//Load user key into array to manipulate
for (int i = 0; i < 8; i++)
{
user_key[i+0] = (K1 >> (56-(i*8))) & 0xFF;
user_key[i+8] = (K2 >> (56-(i*8))) & 0xFF;
}
uint8_t input_register[16];
memset(input_register, 0, sizeof(input_register));
//manipulate user provided key by loading bytes in reverse order into the input_register
for (int i = 0; i < 16; i++)
input_register[15-i] = user_key[i];
uint8_t ks_bytes[16];
memset(ks_bytes, 0, sizeof(ks_bytes));
//create keystream
aes_ofb_keystream_output(input_register, static_key, ks_bytes, 0, 1);
uint8_t ks_bits[128];
memset(ks_bits, 0, sizeof(ks_bits));
unpack_byte_array_into_bit_array(ks_bytes, ks_bits, 16);
//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);
state->tyt_ep = 1;
}

View File

@@ -25,7 +25,6 @@
#include "dmr_const.h"
#include "provoice_const.h"
#include "git_ver.h"
#include "pc4.h"
#include <signal.h>
@@ -34,30 +33,6 @@
#endif
volatile uint8_t exitflag; //fix for issue #136
void tyt_ap_init()
{
unsigned char key1[16] = {0};
unsigned char key2[16] = {0};
char buf[1024];
strncpy(buf, optarg, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
char *pEnd;
uint64_t K1 = strtoull(buf, &pEnd, 16);
uint64_t K2 = strtoull(pEnd, &pEnd, 16);
u64_to_bytes_be(K1, &key1[0]);
u64_to_bytes_be(K2, &key1[8]);
for (int i=0;i<16;i++) key2[i] = key1[15-i];
/* Create key schedule */
create_keys(&ctx, key2, sizeof(key2));
ctx.rounds = nbround;
}
void handler(int sgnl)
{
@@ -2003,89 +1978,17 @@
//get user TYT AP Key and Force Its application
case '!':
tyt_ap_init();
state.tyt_ap = 1;
fprintf (stderr,"DMR TYT AP (PC4) 128-bit Key with Forced Application\n");
tyt_ap_pc4_keystream_creation(&state, optarg);
break;
//get user TYT EP Key and Force Its application
case '5':
//TODO: This, or combine with above with -! AP:KEY or EP:KEY (or similar)
strncpy(opts.szNumbers, optarg, 1023);
opts.szNumbers[1023] = '\0';
unsigned long long int K1 = strtoull (opts.szNumbers, &pEnd, 16);
unsigned long long int K2 = strtoull (pEnd, &pEnd, 16);
uint8_t static_key[32];
memset(static_key, 0, sizeof(static_key));
//static key value
static_key[0]=0x6e; static_key[1]=0x02; static_key[2]=0x8d; static_key[3]=0x8a;
static_key[4]=0xca; static_key[5]=0xeb; static_key[6]=0x9b; static_key[7]=0xbe;
static_key[8]=0x42; static_key[9]=0x72; static_key[10]=0xfb; static_key[11]=0x82;
static_key[12]=0x64; static_key[13]=0x56; static_key[14]=0x31; static_key[15]=0xfa;
//the key value provided by user
uint8_t user_key[16];
memset(user_key, 0, sizeof(user_key));
//Load user key into array to manipulate
for (int i = 0; i < 8; i++)
{
user_key[i+0] = (K1 >> (56-(i*8))) & 0xFF;
user_key[i+8] = (K2 >> (56-(i*8))) & 0xFF;
}
uint8_t input_register[16];
memset(input_register, 0, sizeof(input_register));
//manipulate user provided key by loading bytes in reverse order into the input_register
for (int i = 0; i < 16; i++)
input_register[15-i] = user_key[i];
uint8_t ks_bytes[16];
memset(ks_bytes, 0, sizeof(ks_bytes));
//NOTE: To clarify, TYT EP uses ECB mode with the user key as input_register and the static key in the
//forward (encryption) direction, but we are calling OFB mode because the first round is the
//same concept and we only need the first round output, OFB is easier to use anyways.
//create keystream
aes_ofb_keystream_output(input_register, static_key, ks_bytes, 0, 1);
uint8_t ks_bits[128];
memset(ks_bits, 0, sizeof(ks_bits));
unpack_byte_array_into_bit_array(ks_bytes, ks_bits, 16);
//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);
state.tyt_ep = 1;
tyt_ep_aes_keystream_creation(&state, optarg);
break;
//get user Kenwood DMR Scrambler Key
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, "%d", &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;
ken_dmr_scrambler_keystream_creation(&state, optarg);
break;
case '3':
@@ -3193,36 +3096,6 @@
fprintf (stderr, "Expecting inverted M17 signals.\n");
}
break;
case 'A':
sscanf (optarg, "%i", &opts.mod_threshold);
fprintf (stderr,"Setting C4FM/QPSK auto detection threshold to %i\n", opts.mod_threshold);
break; //this was missing a break
//Disabled and switches reassigned to M17 User Data Argumeents
// case 'S': //disabled, using for M17 encoder user SMS message
// sscanf (optarg, "%i", &opts.ssize);
// if (opts.ssize > 128)
// {
// opts.ssize = 128;
// }
// else if (opts.ssize < 1)
// {
// opts.ssize = 1;
// }
// fprintf (stderr,"Setting QPSK symbol buffer to %i\n", opts.ssize);
// break;
// case 'M': //disabled, using for M17 user data
// sscanf (optarg, "%i", &opts.msize);
// if (opts.msize > 1024)
// {
// opts.msize = 1024;
// }
// else if (opts.msize < 1)
// {
// opts.msize = 1;
// }
// fprintf (stderr,"Setting QPSK Min/Max buffer to %i\n", opts.msize);
// break;
case 'r':
opts.playfiles = 1;