From eb24239c51e64cafbb2dfa1b52e770a18d3a2f60 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sat, 11 Oct 2025 21:02:59 -0400 Subject: [PATCH] DMR: LFSR Function for Kirisun Encryption Methods; #319 Add LFSR to DMR Alg Refresh; Full Link Control and SBLE Tweaks Regarding Kirisun Enc; --- include/dsd.h | 3 +++ src/dmr_flco.c | 6 +++-- src/dmr_le.c | 59 +++++++++++++++++++++++++++++++++++++++++++++----- src/dmr_pi.c | 48 ++++++++++++++++++++++++++++++++++------ 4 files changed, 101 insertions(+), 15 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index c65fc24..df19705 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -1646,6 +1646,9 @@ void ken_dmr_scrambler_keystream_creation(dsd_state * state, char * input); void anytone_bp_keystream_creation(dsd_state * state, char * input); void straight_mod_xor_keystream_creation(dsd_state * state, char * input); +//Kirisun +uint32_t kirisun_lfsr(unsigned long long int mi); + //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); unsigned long long int hytera_lfsr(uint8_t * mi, uint8_t * taps, uint8_t len); diff --git a/src/dmr_flco.c b/src/dmr_flco.c index c5375ae..604df5c 100644 --- a/src/dmr_flco.c +++ b/src/dmr_flco.c @@ -75,8 +75,10 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C //Kirisun if (*IrrecoverableErrors == 0 && CRCCorrect == 1 && fid == 0x0A) //&& (so & 0x40) == 0x40 { - //disable late entry for DMRA, Flag 3 for future checks - opts->dmr_le = 3; + //disable late entry for DMRA, Flag 3 if encrypted, 0 if not + if (so & 0x40) + opts->dmr_le = 3; + else opts->dmr_le = 0; } //read ahead a little to get this for the xpt flag diff --git a/src/dmr_le.c b/src/dmr_le.c index e2beeb7..d504080 100644 --- a/src/dmr_le.c +++ b/src/dmr_le.c @@ -236,6 +236,23 @@ void dmr_alg_refresh (dsd_opts * opts, dsd_state * state) fprintf (stderr, "%s\n", KNRM); } + if (state->payload_algid == 0x35 || state->payload_algid == 0x36 || state->payload_algid == 0x37) + { + state->DMRvcL = 0; + state->payload_mi = kirisun_lfsr(state->payload_mi); + 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(32): %08llX;", state->payload_mi); + fprintf (stderr, " Kirisun"); + if (state->payload_algid == 0x36) + fprintf (stderr, " Advanced;"); + else if (state->payload_algid == 0x37) + fprintf (stderr, " Universal;"); + else fprintf (stderr, " Encryption;"); + fprintf (stderr, "%s\n", KNRM); + } + } if (state->currentslot == 1) { @@ -266,6 +283,23 @@ void dmr_alg_refresh (dsd_opts * opts, dsd_state * state) fprintf (stderr, "%s\n", KNRM); } + if (state->payload_algidR == 0x35 || state->payload_algidR == 0x36 || state->payload_algidR == 0x37) + { + state->DMRvcR = 0; + state->payload_miR = kirisun_lfsr(state->payload_miR); + 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(32): %08llX;", state->payload_miR); + fprintf (stderr, " Kirisun"); + if (state->payload_algidR == 0x36) + fprintf (stderr, " Advanced;"); + else if (state->payload_algidR == 0x37) + fprintf (stderr, " Universal;"); + else fprintf (stderr, " Encryption;"); + fprintf (stderr, "%s\n", KNRM); + } + } } @@ -390,24 +424,37 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power) //NOTE: on above, I belive that we need to check by opcode as well, as a CRC3 can have multiple collisions //so we need to exclude op/alg 0 and 3 from the check (does algID 0x03/0x23 even exist?) + //Kirisun Placeholder if (opts->dmr_le == 3) { - if (sbrc_hex != 0) //Kirisun Placeholder, first had 0x5F1, second batch had 0x5E1 instead + if (irr_err != 0) + { + uint32_t sbrcpl = 0; + for(i = 0; i < 32; i++) + { + sbrcpl = sbrcpl << 1; + sbrcpl |= sbrc_interleaved[i] & 1; + } + if (opts->payload == 0) fprintf (stderr, "\n"); + fprintf (stderr, "%s SLOT %d SB/RC (FEC ERR) E:%d; I:%08X D:%03X; %s ", KRED, slot+1, irr_err, sbrcpl, sbrc_hex, KNRM); + if (opts->payload == 1) fprintf (stderr, "\n"); + } + else if (irr_err == 0 && sbrc_hex != 0) //first batch had sbrc_hex 0x5F1, second batch had 0x5E1 instead, what changed? { fprintf (stderr, "\n"); fprintf (stderr, "%s", KCYN); fprintf (stderr, " Slot %d", state->currentslot+1); - fprintf (stderr, " DMR LE SB Kirisun Encryption;"); + fprintf (stderr, " DMR LE SB Kirisun Encryption Identifier;"); fprintf (stderr, "%s ", KNRM); if (state->currentslot == 0) { - if (state->payload_algid == 0) - state->payload_algid = 0x35; + if (state->payload_algid == 0 && state->dmr_so & 0x40) + state->payload_algid = 0x35; //placeholder value } else { - if (state->payload_algidR == 0) - state->payload_algidR = 0x35; + if (state->payload_algidR == 0 && state->dmr_soR & 0x40) + state->payload_algidR = 0x35; //placeholder value } } } diff --git a/src/dmr_pi.c b/src/dmr_pi.c index a79cdf4..501faa6 100644 --- a/src/dmr_pi.c +++ b/src/dmr_pi.c @@ -36,8 +36,8 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC uint8_t hash = target % 256; //more complex hash later //MI only appears to be 32-bit - unsigned long long int mi = ((unsigned long long int)PI_BYTE[3] << 24) | ((unsigned long long int)PI_BYTE[4] << 16) | - ((unsigned long long int)PI_BYTE[5] << 8) | ((unsigned long long int)PI_BYTE[6] << 0); + uint32_t mi = ((uint32_t)PI_BYTE[3] << 24) | ((uint32_t)PI_BYTE[4] << 16) | + ((uint32_t)PI_BYTE[5] << 8) | ((uint32_t)PI_BYTE[6] << 0); if (state->currentslot == 0) { @@ -56,14 +56,14 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC fprintf (stderr, "%s ", KYEL); fprintf (stderr, "\n Slot %d", state->currentslot+1); - fprintf (stderr, " DMR PI H- ALG ID: %02X; KEY ID: %02X; MI(32): %08llX;", alg, hash, mi); + fprintf (stderr, " DMR PI H- ALG ID: %02X; KEY ID: %02X; MI(32): %08X;", alg, hash, mi); fprintf (stderr, " Kirisun "); if (alg == 0x36) fprintf (stderr, "Advanced;"); else if (alg == 0x37) fprintf (stderr, "Universal;"); - else fprintf (stderr, "Unknown;"); + else fprintf (stderr, "Encryption;"); fprintf (stderr, "%s", KNRM); //disable late entry for DMRA, Flag 3 for future check of VC-F 48-bit region with Golay 24,12 Encoding @@ -473,13 +473,13 @@ unsigned long long int hytera_lfsr(uint8_t * mi, uint8_t * taps, uint8_t len) { uint8_t bit = (mi[i] >> 7) & 1; mi[i] <<= 1; - if (bit) mi[i] ^= taps[i%5]; + if (bit) mi[i] ^= taps[i%len]; mi[i] |= bit; } unsigned long long int mi_value = 0; - for (uint8_t i = 0; i < 5; i++) + for (uint8_t i = 0; i < len; i++) { mi_value <<= 8; mi_value |= mi[i]; @@ -520,4 +520,38 @@ void hytera_enhanced_alg_refresh(dsd_state * state) if (state->currentslot == 0) state->payload_mi = mi_value; else state->payload_miR = mi_value; -} \ No newline at end of file +} + +uint32_t kirisun_lfsr(unsigned long long int mi) +{ + + uint32_t taps = 0xD459C4F1; + uint32_t lfsr = (uint32_t)mi; + uint32_t new_mi = 0; + + for (int i = 0; i < 4; i++) + { + + uint8_t byte = 0; + + for (int j = 0; j < 8; j++) + { + uint32_t temp = (lfsr << 1); + uint8_t msb = (lfsr >> 31) & 1; + + if (msb) + { + byte |= (1 << j); + lfsr = temp ^ taps; + } + else lfsr = temp ^ 1; + } + + new_mi <<=8; + new_mi |= byte; + + } + + return new_mi; + +}