From 934b95cde8b88b718155a8061c8ef737c8f70279 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Thu, 1 May 2025 20:40:35 -0400 Subject: [PATCH] Event History Setup: #287 Make Tweaks / Fixes to DMR Talker Alias; Setup for Hytera Enhanced RC4 Cipher (LFSR Works, Cipher Untested / Unknown Working State); --- include/dsd.h | 4 +++- src/crypt-rc4.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ src/dmr_bs.c | 6 ++++++ src/dmr_le.c | 16 ++++++++++++-- src/dmr_ms.c | 4 ++++ src/dmr_pi.c | 55 +++++++++++++++++++++++++++++++++++++++++++----- src/dsd_alias.c | 12 +++++------ src/dsd_mbe.c | 4 ++-- 8 files changed, 141 insertions(+), 16 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index 2c2bfa8..b0be9ff 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -1586,7 +1586,9 @@ void aes_ctr_bytewise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * payl void aes_ctr_bitwise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * payload, int type); //Hytera Enhanced -void hytera_enhanced_enc_setup(dsd_opts * opts, dsd_state * state, unsigned long long int key_value, unsigned long long int mi_value); +void hytera_enhanced_rc4_setup(dsd_opts * opts, dsd_state * state, unsigned long long int key_value, unsigned long long int mi_value); +unsigned long long int hytera_lfsr(uint8_t * mi, uint8_t * taps, uint8_t len); +void hytera_enhanced_alg_refresh(dsd_state * state); //LFSR to expand either a DMR 32-bit or P25/NXDN 64-bit MI into a 128-bit IV for AES void LFSR128(dsd_state * state); diff --git a/src/crypt-rc4.c b/src/crypt-rc4.c index 6f482be..cea9486 100644 --- a/src/crypt-rc4.c +++ b/src/crypt-rc4.c @@ -86,4 +86,60 @@ void rc4_block_output (int drop, int keylen, int meslen, uint8_t * key, uint8_t } +} + +//NOTE: This has not been verified to work properly +//NOTE: This is for Hytera Enhanced RC4, if AES, this will not work +void hytera_enhanced_rc4_setup(dsd_opts * opts, dsd_state * state, unsigned long long int key_value, unsigned long long int mi_value) +{ + + UNUSED(opts); + uint8_t key[5]; memset (key, 0, sizeof(key)); + uint8_t kiv[5]; memset (kiv, 0, sizeof(kiv)); + uint8_t mi[5]; memset (mi, 0, sizeof(mi)); + uint8_t ks[135]; memset (ks, 0, sizeof(ks)); + + //load key_value into key array + key[0] = ((key_value & 0xFF00000000) >> 32UL); + key[1] = ((key_value & 0xFF000000) >> 24); + key[2] = ((key_value & 0xFF0000) >> 16); + key[3] = ((key_value & 0xFF00) >> 8); + key[4] = ((key_value & 0xFF) >> 0); + + //load mi_value into mi array + mi[0] = ((mi_value & 0xFF00000000) >> 32UL); + mi[1] = ((mi_value & 0xFF000000) >> 24); + mi[2] = ((mi_value & 0xFF0000) >> 16); + mi[3] = ((mi_value & 0xFF00) >> 8); + mi[4] = ((mi_value & 0xFF) >> 0); + + //pointer to the ks_octet storage + uint8_t * ks_octets; + if (state->currentslot == 0) + ks_octets = state->ks_octetL; + else ks_octets = state->ks_octetR; + + rc4_block_output(256, 5, 135, key, ks); + + for (int i = 0; i < 5; i++) + kiv[i] = key[i] ^ mi[i]; + + for (int i = 0; i < 135; i++) + ks_octets[i] = kiv[i%5] ^ ks[i]; + + //debug + // fprintf (stderr, " KS: "); + // for (int i = 0; i < 135; i++) + // { + // if ((i != 0) && ((i%7) == 0)) + // fprintf (stderr, " "); + // fprintf (stderr, "%02X", ks[i]); //ks_octets + // } + + //NULL pointer to ks_octets + ks_octets = NULL; + + //end line break + // fprintf (stderr, "\n"); + } \ No newline at end of file diff --git a/src/dmr_bs.c b/src/dmr_bs.c index cf956a9..858b1cd 100644 --- a/src/dmr_bs.c +++ b/src/dmr_bs.c @@ -425,6 +425,9 @@ void dmrBS (dsd_opts * opts, dsd_state * state) if (internalslot == 0 && vc1 == 6) { + //this needs to run prior to embedded link control + if (state->payload_algid == 0x02) + hytera_enhanced_alg_refresh(state); //process embedded link control fprintf (stderr, "\n"); dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB); @@ -435,6 +438,9 @@ void dmrBS (dsd_opts * opts, dsd_state * state) if (internalslot == 1 && vc2 == 6) { + //this needs to run prior to embedded link control + if (state->payload_algidR == 0x02) + hytera_enhanced_alg_refresh(state); //process embedded link control fprintf (stderr, "\n"); dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB); diff --git a/src/dmr_le.c b/src/dmr_le.c index cf1296e..c51ceea 100644 --- a/src/dmr_le.c +++ b/src/dmr_le.c @@ -227,7 +227,13 @@ void dmr_alg_refresh (dsd_opts * opts, dsd_state * state) if (state->payload_algid == 0x02) { state->DMRvcL = 0; - //LFSR MI propegation function + //LFSR already calculated, just dump it now + fprintf (stderr, "%s", KYEL); + fprintf (stderr, " Slot 1"); + fprintf (stderr, " DMR PI C- ALG ID: %02X; KEY ID: %02X;", state->payload_algid, state->payload_keyid); + fprintf (stderr, " MI(40): %010llX;", state->payload_mi); + fprintf (stderr, " Hytera Enhanced;"); + fprintf (stderr, "%s\n", KNRM); } } @@ -251,7 +257,13 @@ void dmr_alg_refresh (dsd_opts * opts, dsd_state * state) if (state->payload_algidR == 0x02) { state->DMRvcR = 0; - //LFSR MI propegation function + //LFSR already calculated, just dump it now + fprintf (stderr, "%s", KYEL); + fprintf (stderr, " Slot 2"); + fprintf (stderr, " DMR PI C- ALG ID: %02X; KEY ID: %02X;", state->payload_algidR, state->payload_keyidR); + fprintf (stderr, " MI(40): %010llX;", state->payload_miR); + fprintf (stderr, " Hytera Enhanced;"); + fprintf (stderr, "%s\n", KNRM); } } diff --git a/src/dmr_ms.c b/src/dmr_ms.c index 2bd82ca..635c259 100644 --- a/src/dmr_ms.c +++ b/src/dmr_ms.c @@ -274,6 +274,10 @@ void dmrMS (dsd_opts * opts, dsd_state * state) if (vc == 6) { + //this needs to run prior to embedded link control + if (state->payload_algid == 0x02) + hytera_enhanced_alg_refresh(state); + dmr_data_burst_handler(opts, state, (uint8_t *)dummy_bits, 0xEB); //check the single burst/reverse channel opportunity dmr_sbrc (opts, state, power); diff --git a/src/dmr_pi.c b/src/dmr_pi.c index c938581..84ba10e 100644 --- a/src/dmr_pi.c +++ b/src/dmr_pi.c @@ -410,13 +410,58 @@ void LFSR128d(dsd_state * state) } -void hytera_enhanced_enc_setup(dsd_opts * opts, dsd_state * state, unsigned long long int key_value, unsigned long long int mi_value) +unsigned long long int hytera_lfsr(uint8_t * mi, uint8_t * taps, uint8_t len) { - UNUSED(opts); - UNUSED(state); - UNUSED(key_value); - UNUSED(mi_value); + for (uint8_t i = 0; i < len; i++) + { + uint8_t bit = (mi[i] >> 7) & 1; + mi[i] <<= 1; + if (bit) mi[i] ^= taps[i%5]; + mi[i] |= bit; + + } + unsigned long long int mi_value = 0; + for (uint8_t i = 0; i < 5; i++) + { + mi_value <<= 8; + mi_value |= mi[i]; + } + //debug + // fprintf (stderr, " Next MI: %010llX \n", mi_value); + + return mi_value; +} + +void hytera_enhanced_alg_refresh(dsd_state * state) +{ + uint8_t mi[5]; memset (mi, 0, sizeof(mi)); + unsigned long long int mi_value = 0; + if (state->currentslot == 0) + mi_value = state->payload_mi; + else mi_value = state->payload_miR; + + //load mi_value into mi array + mi[0] = ((mi_value & 0xFF00000000) >> 32UL); + mi[1] = ((mi_value & 0xFF000000) >> 24); + mi[2] = ((mi_value & 0xFF0000) >> 16); + mi[3] = ((mi_value & 0xFF00) >> 8); + mi[4] = ((mi_value & 0xFF) >> 0); + + //calculate the next MI value + uint8_t taps[5]; memset(taps, 0, sizeof(taps)); + + //the tap values + taps[0] = 0x12; + taps[1] = 0x24; + taps[2] = 0x48; + taps[3] = 0x22; + taps[4] = 0x14; + mi_value = hytera_lfsr(mi, taps, 5); + + if (state->currentslot == 0) + state->payload_mi = mi_value; + else state->payload_miR = mi_value; } \ No newline at end of file diff --git a/src/dsd_alias.c b/src/dsd_alias.c index 2ffe1a0..6bc10aa 100644 --- a/src/dsd_alias.c +++ b/src/dsd_alias.c @@ -685,9 +685,9 @@ void dmr_talker_alias_lc_blocks (dsd_opts * opts, dsd_state * state, uint8_t slo //set the pointer to the current index of the dmr_pdu_sf if (char_size == 16) - ptr = 48 + (block_num * 48); + ptr = 48 + (block_num * 56); else if (char_size == 8) - ptr = 48 + (block_num * 48); + ptr = 48 + (block_num * 56); else if (char_size == 7) ptr = 49 + (block_num * 56); @@ -717,14 +717,14 @@ void dmr_talker_alias_lc_blocks (dsd_opts * opts, dsd_state * state, uint8_t slo } else if (char_size == 16) { - memcpy(state->dmr_pdu_sf[slot]+ptr, lc_bits+16, 48*sizeof(uint8_t)); - ptr += 48; + memcpy(state->dmr_pdu_sf[slot]+ptr, lc_bits+16, 56*sizeof(uint8_t)); + ptr += 56; if (block_len == 0) end = ptr / 16; else end = block_len; } - dmr_talker_alias_lc_decode (opts, state, slot, block_num, char_size, end); + dmr_talker_alias_lc_decode (opts, state, slot, block_num+1, char_size, end); } } @@ -733,7 +733,7 @@ void dmr_talker_alias_lc_decode (dsd_opts * opts, dsd_state * state, uint8_t slo { UNUSED(opts); uint16_t i = 0; - fprintf (stderr, " Slot %d - Talker Alias Block Num: %d; Valid Block;", slot, block_num+1); + fprintf (stderr, " Slot %d - Talker Alias Block Num: %d; Valid Block;", slot, block_num); fprintf (stderr, " Talker Alias: "); char alias_string[500]; memset (alias_string, 0, sizeof(alias_string)); diff --git a/src/dsd_mbe.c b/src/dsd_mbe.c index 3805069..735bebf 100644 --- a/src/dsd_mbe.c +++ b/src/dsd_mbe.c @@ -775,7 +775,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a if(state->payload_algid == 0x02) { n = 0; - hytera_enhanced_enc_setup(opts, state, state->R, state->payload_mi); + hytera_enhanced_rc4_setup(opts, state, state->R, state->payload_mi); } //Load Keystream Octet Bytes directly into keystream array //TODO: Convert to unpack function @@ -1152,7 +1152,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a if(state->payload_algidR == 0x02) { n = 0; - hytera_enhanced_enc_setup(opts, state, state->RR, state->payload_miR); + hytera_enhanced_rc4_setup(opts, state, state->RR, state->payload_miR); } //Load Keystream Octet Bytes directly into keystream array