DMR: Add More Kirisun Encryption Support; #319

Ciphers added include "Enhanced" "Reinforced" and "Strengthened"; Placeholders for remaining ciphers;
This commit is contained in:
lwvmobile
2026-10-16 11:04:42 -04:00
parent 72b3e5efe4
commit 4005c9b313
10 changed files with 803 additions and 106 deletions

View File

@@ -136,7 +136,7 @@ Advanced Decoder options:
-H '736B9A9C5645288B 243AD5CB8701EF8A'
-H '20029736A5D91042 C923EB0697484433 005EFC58A1905195 E28E9C7836AA2DB8'
-H <hex> Manually Enter AES-128, AES-256, or Kirisun-256 Hex Key (see example below)
-H <hex> Manually Enter AES-128, AES-256, or Kirisun 128 or 256 Hex Key (see example below)
Encapulate in Single Quotation Marks; Space every 16 chars.
-H '736B9A9C5645288B 243AD5CB8701EF8A'
-H '20029736A5D91042 C923EB0697484433 005EFC58A1905195 E28E9C7836AA2DB8'

View File

@@ -1672,10 +1672,9 @@ void vertex_40_keystream_creation(dsd_state * state, unsigned long long int key_
void vertex_256_keystream_creation(dsd_state * state, char * key_string);
void vtx256_ambe2_interleave_inversion(char ambe_fr[4][24]);
//Kirisun
//Kirisun LFSR and General Keystream Creator
uint32_t kirisun_lfsr(unsigned long long int mi);
void kirisun_adv_keystream_creation(dsd_state *state);
void kirisun_uni_keystream_creation(dsd_state *state);
void kirisun_keystream_creation(dsd_state * state);
//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);

View File

@@ -287,7 +287,7 @@ void des_cipher (uint8_t * main_key, uint8_t * input_register, uint8_t * output_
memcpy (left, initial_permutation+0, sizeof(left));
memcpy (right, initial_permutation+4, sizeof(right));
//16 fiestel rounds
//16 feistel rounds
for (uint8_t f = 0; f < 16; f++)
{
@@ -339,7 +339,102 @@ void des_cipher (uint8_t * main_key, uint8_t * input_register, uint8_t * output_
memcpy (left, right, sizeof(left));
memcpy (right, rperm, sizeof(right));
} //end fiestel rounds f
} //end feistel rounds f
//combine right and left into the pre_end_permutation array
memcpy (pre_end_permutation+0, right, sizeof(right));
memcpy (pre_end_permutation+4, left, sizeof(left));
//carry out the final permuation to get the completed output_register for this cipher iteration
permute (pre_end_permutation, output_register, final_register_permutation, 0, 64);
}
//kirisun variation on this cipher w/ preconfigured unique key schedule
void ksun_des_cipher (uint8_t * key, uint8_t * input_register, uint8_t * output_register, uint8_t de)
{
//starting and ending permutations
uint8_t initial_permutation[8]; memset(initial_permutation, 0, sizeof(initial_permutation));
uint8_t pre_end_permutation[8]; memset(pre_end_permutation, 0, sizeof(pre_end_permutation));
//intermediate left, right, and expansion/selection arrays
uint8_t left[4]; memset(left, 0, sizeof(left));
uint8_t right[4]; memset(right, 0, sizeof(right));
uint8_t rperm[4]; memset(rperm, 0, sizeof(rperm));
uint8_t exp[6]; memset(exp, 0, sizeof(exp));
uint8_t sel[4]; memset(sel, 0, sizeof(sel));
//key sets
uint8_t Ks[16][6]; memset(Ks, 0, sizeof(Ks));
//file the key into the keysets
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 6; j++)
Ks[i][j] = key[(i*6) + j];
}
//permute the input_register with the ip (initial_register_permutation) table
permute (input_register, initial_permutation, initial_register_permutation, 0, 64);
//copy the initial permutation to left and right half arrays
memcpy (left, initial_permutation+0, sizeof(left));
memcpy (right, initial_permutation+4, sizeof(right));
//16 feistel rounds
for (uint8_t f = 0; f < 16; f++)
{
//reset rperm and exp arrays
memset(rperm, 0, sizeof(rperm));
memset(exp, 0, sizeof(exp));
//expand right half from 32-bit to 48-bit
permute (right, exp, message_expansion, 0, 48);
//apply current iteration keyset to the expanded array (encryption cycles Ks forward, decryption goes in reverse)
if (de == 1)
{
for (uint8_t i = 0; i < 6; i++)
exp[i] ^= Ks[f][i];
}
else
{
for (uint8_t i = 0; i < 6; i++)
exp[i] ^= Ks[15-f][i];
}
//extract 6 bits for each sbox swap from the expanded array
uint8_t e1 = exp[0] >> 2;
uint8_t e2 = ((exp[0] & 0x3) << 4) | (exp[1] >> 4);
uint8_t e3 = ((exp[1] & 0xF) << 2) | (exp[2] >> 6);
uint8_t e4 = exp[2] & 0x3F;
uint8_t e5 = exp[3] >> 2;
uint8_t e6 = ((exp[3] & 0x3) << 4) | (exp[4] >> 4);
uint8_t e7 = ((exp[4] & 0xF) << 2) | (exp[5] >> 6);
uint8_t e8 = exp[5] & 0x3F;
//select 32-bits of each 48-bit expansion via modified S Box Look Up Tables
//swap the 6 bits for 4 bits via SLUT tables and OR them together into a selection array
sel[0] = SLUT1[e1] | SLUT2[e2];
sel[1] = SLUT3[e3] | SLUT4[e4];
sel[2] = SLUT5[e5] | SLUT6[e6];
sel[3] = SLUT7[e7] | SLUT8[e8];
//permute the selected 32-bits into a new right half
permute (sel, rperm, right_half_permutation, 0, 32);
//xor new right half against left half
for (uint8_t i = 0; i < 4; i++)
rperm[i] ^= left[i];
//swap old right half to left, set new right half to rperm
memcpy (left, right, sizeof(left));
memcpy (right, rperm, sizeof(right));
} //end feistel rounds f
//combine right and left into the pre_end_permutation array
memcpy (pre_end_permutation+0, right, sizeof(right));

View File

@@ -1,6 +1,9 @@
#include "dsd.h"
#include "pc4.h"
//function prototype linked in crypt-des.c
void ksun_des_cipher (uint8_t * key, uint8_t * input_register, uint8_t * output_register, uint8_t de);
/* === Global MD2II buffers === */
int x1, x2, i, n1global;
unsigned char h2[n1];
@@ -174,7 +177,68 @@ void keystream37(unsigned char *key, uint64_t frame, unsigned char *output)
}
//dsd-fme -fs -Z -i '/SSD_STORAGE/2025_DEV/Tytera BP EP AP Master Folder/kirisun/cap-clear.wav/cap-33.wav' -H '3333333333333333 3333333333333333 3333333333333333 3333333333333333'
#define ROTATE_LEFT(VALUE, SHIFT) \
(((VALUE) << ((SHIFT) & 63)) | ((VALUE) >> (64 - ((SHIFT) & 63))))
#define ROTATE_RIGHT(VALUE, SHIFT) \
(((VALUE) >> ((SHIFT) & 63)) | ((VALUE) << (64 - ((SHIFT) & 63))))
void keystream35(uint8_t * input_register, unsigned char * key)
{
uint64_t round = 0x9E3779B97F4A7C15;
uint64_t round_key[2]; memset(round_key, 0, sizeof(round_key));
uint64_t state[2]; memset(state, 0, sizeof(state));
//load input_register into state as two 64-bit chunks
for (int i = 0; i < 8; i++)
{
state[0] <<= 8;
state[0] |= input_register[i+0];
state[1] <<= 8;
state[1] |= input_register[i+8];
}
//load key into round_key as two 64-bit chunks
for (int i = 0; i < 8; i++)
{
round_key[0] <<= 8;
round_key[0] |= key[i+0];
round_key[1] <<= 8;
round_key[1] |= key[i+8];
}
for (int i = 0; i < 64; i++)
{
round_key[0] += round;
round_key[1] -= round;
state[0] ^= round_key[0];
state[0] += state[1];
state[0] = ROTATE_LEFT(state[0], state[1]);
state[1] = ROTATE_RIGHT(state[1], state[0]);
state[1] -= state[0];
state[1] ^= round_key[1];
}
uint64_t temp = state[0];
state[0] = state[1];
state[1] = temp;
//reload input_register with current state values
for (int i = 0; i < 8; i++)
input_register[i+0] = (state[0] >> (56 - (i * 8))) & 0xFF;
for (int i = 0; i < 8; i++)
input_register[i+8] = (state[1] >> (56 - (i * 8))) & 0xFF;
}
//dsd-fme -fs -Z -i 'SSD_STORAGE/2025_DEV/Tytera BP EP AP Master Folder/kirisun/cap-clear.wav/cap-33.wav' -H '3333333333333333 3333333333333333 3333333333333333 3333333333333333'
void kirisun_uni_keystream_creation(dsd_state *state)
{
uint8_t slot = 0;
@@ -292,7 +356,7 @@ void kirisun_uni_keystream_creation(dsd_state *state)
}
//dsd-fme -fs -Z -i '/SSD_STORAGE/2025_DEV/Tytera BP EP AP Master Folder/kirisun/better_samples_tg1/kirisun_advanced_tg1.wav' -H 'DC1A7E9F9BF312DB F45010CEC5F7A53A C407D0BFA803617B E426A7254DA9390D'
//dsd-fme -fs -Z -i 'SSD_STORAGE/2025_DEV/Tytera BP EP AP Master Folder/kirisun/better_samples_tg1/kirisun_advanced_tg1.wav' -H 'DC1A7E9F9BF312DB F45010CEC5F7A53A C407D0BFA803617B E426A7254DA9390D'
void kirisun_adv_keystream_creation(dsd_state *state)
{
@@ -415,3 +479,462 @@ void kirisun_adv_keystream_creation(dsd_state *state)
}
}
//dsd-fme -fs -Z -i 'SSD_STORAGE/2025_DEV/Tytera BP EP AP Master Folder/kirisun/enhanced-key-12.wav/enhanced-key-12.wav' -H 'C607727B8BECC3CB 7DD174F5526BB546'
void kirisun_enh_keystream_creation(dsd_state *state)
{
uint8_t slot = 0;
if (state->currentslot == 0)
slot = 0;
else slot = 1;
uint32_t lfsr = 0;
if (state->currentslot == 0)
lfsr = (uint32_t)state->payload_mi;
else lfsr = (uint32_t)state->payload_miR;
unsigned char userkeyhexa[32]; memset(userkeyhexa, 0, sizeof(userkeyhexa));
unsigned char realkey[32]; memset(realkey, 0, sizeof(realkey));
unsigned char lfsrhexa[4]; memset(lfsrhexa, 0, sizeof(lfsrhexa));
uint8_t ks_bytes[128]; memset(ks_bytes, 0, sizeof(ks_bytes));
lfsrhexa[0] = (lfsr >> 24) & 0xFF;
lfsrhexa[1] = (lfsr >> 16) & 0xFF;
lfsrhexa[2] = (lfsr >> 8) & 0xFF;
lfsrhexa[3] = (lfsr >> 0) & 0xFF;
uint64_t K1 = state->A1[slot];
uint64_t K2 = state->A2[slot];
if (K1 != 0 && K2 != 0)
state->aes_key_loaded[slot] = 1;
else state->aes_key_loaded[slot] = 0;
if (state->aes_key_loaded[slot] == 1)
{
u64_to_bytes_be(K1, &userkeyhexa[0]);
u64_to_bytes_be(K2, &userkeyhexa[8]);
// printf("=== userkey input (16 bytes) ===\n");
// print_hex(userkeyhexa,16);
/* --- MD2II first pass --- */
n1global=16;
unsigned char h4[n1]; memset(h4, 0, sizeof(h4));
MD2II_init();
MD2II_hashing(userkeyhexa,16);
MD2II_end(h4);
for(int i=0;i<16;i++) realkey[i]=h4[i];
// printf("=== realkey final (16 bytes) ===\n");
// print_hex(realkey,16);
n1global=16;
MD2II_init();
MD2II_hashing(lfsrhexa,4);
MD2II_hashing(realkey,16);
MD2II_end(h4);
uint8_t input_register[16]; memset(input_register, 0, sizeof(input_register));
//copy h4 to the input_register for the cipher
memcpy(input_register, h4, 16);
/* --- MD2II with n1global=32 --- */
n1global=32;
MD2II_init();
MD2II_hashing(lfsrhexa,4);
MD2II_hashing(realkey,16);
MD2II_end(h4);
//copy h4 to the tab for the cipher
uint8_t tab[16]; memset(tab, 0, sizeof(tab));
memcpy(tab, h4, 16);
// printf("=== Input Register (16 bytes) ===\n");
// print_hex(input_register,16);
// printf("=== Tab (16 bytes) ===\n");
// print_hex(tab,16);
/* --- keystream output --- */
uint8_t output[128]; memset(output, 0, sizeof(output));
//discard round
keystream35(input_register, tab);
for (int i = 0; i < 8; i++)
{
keystream35(input_register, tab);
memcpy(output+(i*16), input_register, 16);
}
//store ks_bytes to storage
for (int i = 0; i < 128; i++)
ks_bytes[i] = output[i];
if (slot == 0)
memcpy(state->ks_octetL, ks_bytes, sizeof(ks_bytes));
else memcpy(state->ks_octetR, ks_bytes, sizeof(ks_bytes));
//debug ks_bytes
// fprintf (stderr, "KS: ");
// for (int i = 0; i < 128; i++)
// {
// if ((i != 0) && ((i%16)==0))
// fprintf (stderr, "\n ");
// fprintf (stderr, "%02X ", ks_bytes[i]);
// }
// fprintf (stderr, "\n");
}
}
//dsd-fme -fs -Z -i 'SSD_STORAGE/2025_DEV/Tytera BP EP AP Master Folder/kirisun/kirisun_files/reinforced-key-9.wav' -H 'C607727B8BECC3CB 7DD174F5526BB546 B3DEA1C111DC1994 69243120CDB6F99A'
void kirisun_rei_keystream_creation(dsd_state *state)
{
uint8_t slot = 0;
if (state->currentslot == 0)
slot = 0;
else slot = 1;
uint32_t lfsr = 0;
if (state->currentslot == 0)
lfsr = (uint32_t)state->payload_mi;
else lfsr = (uint32_t)state->payload_miR;
unsigned char userkeyhexa[32]; memset(userkeyhexa, 0, sizeof(userkeyhexa));
unsigned char realkey[32]; memset(realkey, 0, sizeof(realkey));
unsigned char lfsrhexa[4]; memset(lfsrhexa, 0, sizeof(lfsrhexa));
uint8_t ks_bytes[128]; memset(ks_bytes, 0, sizeof(ks_bytes));
lfsrhexa[0] = (lfsr >> 24) & 0xFF;
lfsrhexa[1] = (lfsr >> 16) & 0xFF;
lfsrhexa[2] = (lfsr >> 8) & 0xFF;
lfsrhexa[3] = (lfsr >> 0) & 0xFF;
uint64_t K1 = state->A1[slot];
uint64_t K2 = state->A2[slot];
uint64_t K3 = state->A3[slot];
uint64_t K4 = state->A4[slot];
if (K1 != 0 && K2 != 0 && K3 != 0 && K4 != 0)
state->aes_key_loaded[slot] = 1;
else state->aes_key_loaded[slot] = 0;
if (state->aes_key_loaded[slot] == 1)
{
u64_to_bytes_be(K1, &userkeyhexa[0]);
u64_to_bytes_be(K2, &userkeyhexa[8]);
u64_to_bytes_be(K3, &userkeyhexa[16]);
u64_to_bytes_be(K4, &userkeyhexa[24]);
for(int i=0;i<32;i++) realkey[i]=userkeyhexa[i];
// printf("=== userkey input (32 bytes) ===\n");
// print_hex(userkeyhexa,32);
/* --- MD2II first pass --- */
n1global=32;
unsigned char h4[n1]; memset(h4, 0, sizeof(h4));
MD2II_init();
MD2II_hashing(realkey,32);
MD2II_end(h4);
for(int i=0;i<32;i++) realkey[i]=h4[i];
// printf("=== realkey final (32 bytes) ===\n");
// print_hex(realkey,32);
n1global=8;
MD2II_init();
MD2II_hashing(lfsrhexa,4);
MD2II_hashing(realkey,32);
MD2II_end(h4);
// printf("h4[0..7]: ");
// print_hex(h4,8);
uint64_t internal_state=0;
for(int i=0;i<8;i++)
internal_state=(internal_state<<8)+(h4[i]);
// printf("internal_state=%016llX\n",(unsigned long long)internal_state);
uint8_t input_register[8]; memset(input_register, 0, sizeof(input_register));
uint8_t output_register[8]; memset(output_register, 0, sizeof(output_register));
//copy internal state value to the input_register for the modified DES cipher
memcpy(input_register, h4, 8);
/* --- MD2II with n1global=96 --- */
n1global=96;
MD2II_init();
MD2II_hashing(lfsrhexa,4);
MD2II_hashing(realkey,32);
MD2II_end(h4);
// printf("realkey (96 bytes):\n");
// print_hex(h4,96);
/* --- keystream output --- */
uint8_t output[128]; memset(output, 0, sizeof(output));
//run discard round first
ksun_des_cipher(h4, input_register, output_register, 1);
memcpy(input_register, output_register, 8); //internal_state = des_reinforced(internal_state, encrypt);
memset(output_register, 0, sizeof(output_register));
//begin creation of actual keystream now
for (int i = 0; i < 16; i++)
{
//the internal state is the output feedback mode
ksun_des_cipher(h4, input_register, output_register, 1);
memcpy(output+(i*8), output_register, 8);
memcpy(input_register, output_register, 8);
memset(output_register, 0, sizeof(output_register));
}
// printf("keystream output (128 bytes):\n");
// print_hex(output,128);
//store ks_bytes to storage
for (int i = 0; i < 128; i++)
ks_bytes[i] = output[i];
if (slot == 0)
memcpy(state->ks_octetL, ks_bytes, sizeof(ks_bytes));
else memcpy(state->ks_octetR, ks_bytes, sizeof(ks_bytes));
//debug ks_bytes
// fprintf (stderr, "KS: ");
// for (int i = 0; i < 128; i++)
// {
// if ((i != 0) && ((i%16)==0))
// fprintf (stderr, "\n ");
// fprintf (stderr, "%02X ", ks_bytes[i]);
// }
// fprintf (stderr, "\n");
}
}
//dsd-fme -fs -Z -i 'SSD_STORAGE/2025_DEV/Tytera BP EP AP Master Folder/kirisun/kirisun_files/strengthened-key-7.wav' -H 'C607727B8BECC3CB 7DD174F5526BB546 B3DEA1C111DC1994 69243120CDB6F99A'
void kirisun_str_keystream_creation(dsd_state *state)
{
uint8_t slot = 0;
if (state->currentslot == 0)
slot = 0;
else slot = 1;
uint32_t lfsr = 0;
if (state->currentslot == 0)
lfsr = (uint32_t)state->payload_mi;
else lfsr = (uint32_t)state->payload_miR;
unsigned char userkeyhexa[32]; memset(userkeyhexa, 0, sizeof(userkeyhexa));
unsigned char realkey[32]; memset(realkey, 0, sizeof(realkey));
unsigned char lfsrhexa[4]; memset(lfsrhexa, 0, sizeof(lfsrhexa));
uint8_t ks_bytes[128]; memset(ks_bytes, 0, sizeof(ks_bytes));
uint8_t global_key[288]; memset (global_key, 0, sizeof(global_key));
lfsrhexa[0] = (lfsr >> 24) & 0xFF;
lfsrhexa[1] = (lfsr >> 16) & 0xFF;
lfsrhexa[2] = (lfsr >> 8) & 0xFF;
lfsrhexa[3] = (lfsr >> 0) & 0xFF;
uint64_t K1 = state->A1[slot];
uint64_t K2 = state->A2[slot];
uint64_t K3 = state->A3[slot];
uint64_t K4 = state->A4[slot];
if (K1 != 0 && K2 != 0 && K3 != 0 && K4 != 0)
state->aes_key_loaded[slot] = 1;
else state->aes_key_loaded[slot] = 0;
if (state->aes_key_loaded[slot] == 1)
{
u64_to_bytes_be(K1, &userkeyhexa[0]);
u64_to_bytes_be(K2, &userkeyhexa[8]);
u64_to_bytes_be(K3, &userkeyhexa[16]);
u64_to_bytes_be(K4, &userkeyhexa[24]);
for(int i=0;i<32;i++) realkey[i]=userkeyhexa[i];
// printf("=== userkey input (32 bytes) ===\n");
// print_hex(userkeyhexa,32);
/* --- MD2II first pass --- */
n1global=32;
unsigned char h4[288]; memset(h4, 0, sizeof(h4));
MD2II_init();
MD2II_hashing(realkey,32);
MD2II_end(h4);
for(int i=0;i<32;i++) realkey[i]=h4[i];
// printf("=== realkey final (32 bytes) ===\n");
// print_hex(realkey,32);
n1global=288;
MD2II_init();
MD2II_hashing(realkey, 32);
MD2II_end(h4);
for (int i=0;i<288;i++) global_key[i]=h4[i];
// printf("=== global key (288 bytes) ===\n");
// print_hex(realkey,288);
n1global=8;
MD2II_init();
MD2II_hashing(lfsrhexa,4);
MD2II_hashing(realkey,32);
MD2II_end(h4);
// printf("h4[0..7]: ");
// print_hex(h4,8);
uint64_t internal_state=0;
for(int i=0;i<8;i++)
internal_state=(internal_state<<8)+(h4[i]);
// printf("internal_state=%016llX\n",(unsigned long long)internal_state);
uint8_t input_register[8]; memset(input_register, 0, sizeof(input_register));
uint8_t output_register[8]; memset(output_register, 0, sizeof(output_register));
//copy internal state value to the input_register for the modified DES cipher
memcpy(input_register, h4, 8);
/* --- MD2II with n1global=96 --- */
n1global=96;
MD2II_init();
MD2II_hashing(lfsrhexa,4);
MD2II_hashing(realkey,32);
MD2II_end(h4);
// printf("realkey (96 bytes):\n");
// print_hex(h4,96);
/* --- keystream output --- */
uint8_t output[128]; memset(output, 0, sizeof(output));
//run discard round first
ksun_des_cipher(global_key+0, input_register, output_register, 1);
memcpy(input_register, output_register, 8); //internal_state = des_reinforced(internal_state, encrypt);
memset(output_register, 0, sizeof(output_register));
ksun_des_cipher(global_key+96, input_register, output_register, 0);
memcpy(input_register, output_register, 8); //internal_state = des_reinforced(internal_state, encrypt);
memset(output_register, 0, sizeof(output_register));
ksun_des_cipher(global_key+192, input_register, output_register, 1);
memcpy(input_register, output_register, 8); //internal_state = des_reinforced(internal_state, encrypt);
memset(output_register, 0, sizeof(output_register));
//begin creation of actual keystream now
for (int i = 0; i < 16; i++)
{
//the internal state is the output feedback mode
ksun_des_cipher(global_key+0, input_register, output_register, 1);
memcpy(input_register, output_register, 8); //internal_state = des_reinforced(internal_state, encrypt);
memset(output_register, 0, sizeof(output_register));
ksun_des_cipher(global_key+96, input_register, output_register, 0);
memcpy(input_register, output_register, 8); //internal_state = des_reinforced(internal_state, encrypt);
memset(output_register, 0, sizeof(output_register));
ksun_des_cipher(global_key+192, input_register, output_register, 1);
memcpy(input_register, output_register, 8); //internal_state = des_reinforced(internal_state, encrypt);
//copy out last output_register to output
memcpy(output+(i*8), output_register, 8);
memset(output_register, 0, sizeof(output_register));
}
// printf("keystream output (128 bytes):\n");
// print_hex(output,128);
//store ks_bytes to storage
for (int i = 0; i < 128; i++)
ks_bytes[i] = output[i];
if (slot == 0)
memcpy(state->ks_octetL, ks_bytes, sizeof(ks_bytes));
else memcpy(state->ks_octetR, ks_bytes, sizeof(ks_bytes));
//debug ks_bytes
// fprintf (stderr, "KS: ");
// for (int i = 0; i < 128; i++)
// {
// if ((i != 0) && ((i%16)==0))
// fprintf (stderr, "\n ");
// fprintf (stderr, "%02X ", ks_bytes[i]);
// }
// fprintf (stderr, "\n");
}
}
void kirisun_low_keystream_creation(dsd_state *state)
{
UNUSED(state);
}
void kirisun_mid_keystream_creation(dsd_state *state)
{
UNUSED(state);
}
void kirisun_hi_keystream_creation(dsd_state *state)
{
UNUSED(state);
}
void kirisun_top_keystream_creation(dsd_state *state)
{
UNUSED(state);
}
void kirisun_ult_keystream_creation(dsd_state *state)
{
UNUSED(state);
}
//General Keystream Creator for any known Kirisun cipher
void kirisun_keystream_creation(dsd_state * state)
{
if (state->payload_algid == 0x31)
kirisun_rei_keystream_creation(state);
else if (state->payload_algid == 0x32)
kirisun_low_keystream_creation(state);
else if (state->payload_algid == 0x33)
kirisun_mid_keystream_creation(state);
else if (state->payload_algid == 0x34)
kirisun_hi_keystream_creation(state);
else if (state->payload_algid == 0x35)
kirisun_enh_keystream_creation(state);
else if (state->payload_algid == 0x36)
kirisun_adv_keystream_creation(state);
else if (state->payload_algid == 0x37)
kirisun_uni_keystream_creation(state);
else if (state->payload_algid == 0x38)
kirisun_str_keystream_creation(state);
else if (state->payload_algid == 0x39)
kirisun_top_keystream_creation(state);
else if (state->payload_algid == 0x3A)
kirisun_ult_keystream_creation(state);
}

View File

@@ -219,20 +219,37 @@ 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)
if ((state->payload_algid & 0xF0) == 0x30) //any kirisun 0x3X alg
{
uint8_t alg = state->payload_algid;
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, " DMR PI C- ALG ID: %02X; KEY ID: %02X;", alg, 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, " Kirisun ");
if (alg == 0x31)
fprintf (stderr, "Reinforced ");
else if (alg == 0x32)
fprintf (stderr, "Low ");
else if (alg == 0x33)
fprintf (stderr, "Middle ");
else if (alg == 0x34)
fprintf (stderr, "High ");
else if (alg == 0x35)
fprintf (stderr, "Enhanced ");
else if (alg == 0x36)
fprintf (stderr, "Advanced ");
else if (alg == 0x37)
fprintf (stderr, "Universal ");
else if (alg == 0x38)
fprintf (stderr, "Strengthened ");
else if (alg == 0x39)
fprintf (stderr, "Top ");
else if (alg == 0x3A)
fprintf (stderr, "Ultra ");
fprintf (stderr, "Encryption;");
fprintf (stderr, "%s\n", KNRM);
}
@@ -266,20 +283,37 @@ 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)
if ((state->payload_algidR & 0xF0) == 0x30) //any 0x3X alg
{
uint8_t alg = state->payload_algidR;
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, " DMR PI C- ALG ID: %02X; KEY ID: %02X;", alg, 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, " Kirisun ");
if (alg == 0x31)
fprintf (stderr, "Reinforced ");
else if (alg == 0x32)
fprintf (stderr, "Low ");
else if (alg == 0x33)
fprintf (stderr, "Middle ");
else if (alg == 0x34)
fprintf (stderr, "High ");
else if (alg == 0x35)
fprintf (stderr, "Enhanced ");
else if (alg == 0x36)
fprintf (stderr, "Advanced ");
else if (alg == 0x37)
fprintf (stderr, "Universal ");
else if (alg == 0x38)
fprintf (stderr, "Strengthened ");
else if (alg == 0x39)
fprintf (stderr, "Top ");
else if (alg == 0x3A)
fprintf (stderr, "Ultra ");
fprintf (stderr, "Encryption;");
fprintf (stderr, "%s\n", KNRM);
}
@@ -407,7 +441,7 @@ 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
//Kirisun
if (opts->dmr_le == 3)
{
if (irr_err != 0)
@@ -422,23 +456,38 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
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?
else if (irr_err == 0 && sbrc_hex != 0) //older firmware had sbrc_hex 0x5F1, and 0x5E1 instead
{
fprintf (stderr, "\n");
fprintf (stderr, "%s", KCYN);
fprintf (stderr, " Slot %d", state->currentslot+1);
fprintf (stderr, " DMR LE SB Kirisun Encryption Identifier;");
fprintf (stderr, " DMR LE SB Kirisun");
//Newer Samples and/or updated firmware seem to do this with actual key values
uint8_t alg = sbrc_hex >> 7;
if (alg != 0xB)
{
fprintf (stderr, " ALG: %02X;", alg+0x30);
uint8_t kid = (sbrc_hex >> 3) & 0xF;
fprintf (stderr, " KID: %02X;", kid);
uint8_t unk = sbrc_hex & 0x7;
fprintf (stderr, " LOW3: %X;", unk);
if (state->currentslot == 0)
{
if (state->payload_algid == 0 && state->dmr_so & 0x40)
state->payload_algid = alg+0x30;
}
else
{
if (state->payload_algidR == 0 && state->dmr_soR & 0x40)
state->payload_algidR = alg+0x30;
}
}
fprintf (stderr, "%s ", KNRM);
if (state->currentslot == 0)
{
if (state->payload_algid == 0 && state->dmr_so & 0x40)
state->payload_algid = 0x35; //placeholder value
}
else
{
if (state->payload_algidR == 0 && state->dmr_soR & 0x40)
state->payload_algidR = 0x35; //placeholder value
}
}
}

View File

@@ -27,43 +27,65 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC
if (MFID == 0x0A && CRCCorrect == 1) //Kirisun
{
uint8_t so = PI_BYTE[2]; //in VLC and PI, this byte is 0x40, so thinking this could be SVC_OPT
//NOTE: Some Kirisun Radios seem to use byte 2 as the SVC_OPT, others seem to use it like a KID value
// uint8_t so = PI_BYTE[2]; //in VLC and PI, this byte is 0x40, so thinking this could be SVC_OPT
uint8_t alg = PI_BYTE[0]; //observed 0x36 and 0x37 for Kirisun Advanced and Universal Privacy
// uint8_t kid = PI_BYTE[2]; //user info conveyed there is only 16 allotments for Key, and keys are channel specific, so no key id value
//NOTE: Original samples had this as 0x40 no matter which "key" was selected, new samples from different radio show a KID value
uint8_t kid = PI_BYTE[2]; //user info conveyed there is only 16 allotments for Key, and keys are channel specific, so no key id value on older FW
uint32_t target = ((unsigned long long int)PI_BYTE[7] << 16) | ((unsigned long long int)PI_BYTE[8] << 8) | ((unsigned long long int)PI_BYTE[9] << 0);
//TODO: Use ALG and TGT value here to produce a key id via hashing it
uint8_t hash = alg * target % 256; //more complex hash later (honestly, probably not)
//Only set real KID if the byte value isn't 0x40
if (kid == 0x40)
kid = hash;
//MI only appears to be 32-bit
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)
{
state->dmr_so = so;
state->payload_algid = alg;
state->payload_keyid = hash;
state->dmr_so = 0x40;
state->payload_algid = alg;
state->payload_keyid = kid;
state->payload_mi = mi;
}
else
{
state->dmr_soR = so;
state->dmr_soR = 0x40;
state->payload_algidR = alg;
state->payload_keyidR = hash;
state->payload_keyidR = kid;
state->payload_miR = mi;
}
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): %08X;", alg, hash, mi);
fprintf (stderr, " DMR PI H- ALG ID: %02X; TGT: %d; KEY ID: %02X; MI(32): %08X;", alg, target, kid, mi);
fprintf (stderr, " Kirisun ");
if (alg == 0x36)
fprintf (stderr, "Advanced;");
if (alg == 0x31)
fprintf (stderr, "Reinforced ");
else if (alg == 0x32)
fprintf (stderr, "Low ");
else if (alg == 0x33)
fprintf (stderr, "Middle ");
else if (alg == 0x34)
fprintf (stderr, "High ");
else if (alg == 0x35)
fprintf (stderr, "Enhanced ");
else if (alg == 0x36)
fprintf (stderr, "Advanced ");
else if (alg == 0x37)
fprintf (stderr, "Universal;");
else fprintf (stderr, "Encryption;");
fprintf (stderr, "Universal ");
else if (alg == 0x38)
fprintf (stderr, "Strengthened ");
else if (alg == 0x39)
fprintf (stderr, "Top ");
else if (alg == 0x3A)
fprintf (stderr, "Ultra ");
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

View File

@@ -104,7 +104,15 @@ void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state)
encL = 0;
}
}
else if (state->payload_algid == 0x24 || state->payload_algid == 0x25 || state->payload_algid == 0x36 || state->payload_algid == 0x37)
else if (state->payload_algid == 0x24 || state->payload_algid == 0x25)
{
//going to need a better check for this later on, or seperated keys or something
if (state->aes_key_loaded[0] == 1)
{
encL = 0;
}
}
else if (state->payload_algid >= 0x31 && state->payload_algid <= 0x3A)
{
//going to need a better check for this later on, or seperated keys or something
if (state->aes_key_loaded[0] == 1)
@@ -141,7 +149,15 @@ void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state)
encR = 0;
}
}
else if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25 || state->payload_algidR == 0x36 || state->payload_algidR == 0x37)
else if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25)
{
//going to need a better check for this later on, or seperated keys or something
if (state->aes_key_loaded[1] == 1)
{
encR = 0;
}
}
else if (state->payload_algidR >= 0x31 && state->payload_algidR <= 0x3A)
{
//going to need a better check for this later on, or seperated keys or something
if (state->aes_key_loaded[1] == 1)
@@ -738,13 +754,28 @@ void playSynthesizedVoiceFM (dsd_opts * opts, dsd_state * state)
encL = 0;
}
}
else if (state->payload_algid == 0x84 || state->payload_algid == 0x89 || state->nxdn_cipher_type == 0x3 || state->payload_algid == 0x36 || state->payload_algid == 0x37)
else if (state->payload_algid == 0x84 || state->payload_algid == 0x89 || state->nxdn_cipher_type == 0x3)
{
if (state->aes_key_loaded[0] == 1)
{
encL = 0;
}
}
else if (state->payload_algid >= 0x31 && state->payload_algid <= 0x3A)
{
//going to need a better check for this later on, or seperated keys or something
if (state->aes_key_loaded[0] == 1)
{
encL = 0;
}
}
else if (state->payload_algidR == 0x26)
{
if (state->straight_ks == 0x26)
{
encL = 0;
}
}
}
//WIP: Mute if on B list (or not W list)
@@ -1157,7 +1188,15 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
encL = 0;
}
}
else if (state->payload_algid == 0x24 || state->payload_algid == 0x25 || state->payload_algid == 0x36 || state->payload_algid == 0x37)
else if (state->payload_algid == 0x24 || state->payload_algid == 0x25)
{
//going to need a better check for this later on, or seperated keys or something
if (state->aes_key_loaded[0] == 1)
{
encL = 0;
}
}
else if (state->payload_algid >= 0x31 && state->payload_algid <= 0x3A)
{
//going to need a better check for this later on, or seperated keys or something
if (state->aes_key_loaded[0] == 1)
@@ -1194,7 +1233,15 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
encR = 0;
}
}
else if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25 || state->payload_algidR == 0x36 || state->payload_algidR == 0x37)
else if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25)
{
//going to need a better check for this later on, or seperated keys or something
if (state->aes_key_loaded[1] == 1)
{
encR = 0;
}
}
else if (state->payload_algidR >= 0x31 && state->payload_algidR <= 0x3A)
{
//going to need a better check for this later on, or seperated keys or something
if (state->aes_key_loaded[1] == 1)

View File

@@ -1542,7 +1542,7 @@
printf (" -H '736B9A9C5645288B 243AD5CB8701EF8A' \n");
printf (" -H '20029736A5D91042 C923EB0697484433 005EFC58A1905195 E28E9C7836AA2DB8' \n");
printf ("\n");
printf (" -H <hex> Manually Enter AES-128, AES-256, or Kirisun-256 Hex Key (see example below)\n");
printf (" -H <hex> Manually Enter AES-128, AES-256, or Kirisun 128 or 256 Hex Key (see example below)\n");
printf (" Encapulate in Single Quotation Marks; Space every 16 chars.\n");
printf (" -H '736B9A9C5645288B 243AD5CB8701EF8A' \n");
printf (" -H '20029736A5D91042 C923EB0697484433 005EFC58A1905195 E28E9C7836AA2DB8' \n");

View File

@@ -304,9 +304,9 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
if (state->payload_algid == 0x9F) //DES-XL
des_multi_keystream_output (state->payload_miP, state->R, state->ks_octetL, 2, state->xl_is_hdu); //hard coded bit count value, xl_is_hdu determines lfsr run values
if (state->payload_algid == 0x84) //AES256
aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 2, 14); //14 + 1 discard round
aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 2, 16); //15 + 1 discard round
if (state->payload_algid == 0x89) //AES128
aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 0, 14); //14 + 1 discard round
aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 0, 16); //15 + 1 discard round
}
@@ -779,8 +779,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
(state->currentslot == 0 && state->payload_algid == 0x25 && state->aes_key_loaded[0] == 1 ) || //DMR AES256
(state->currentslot == 0 && state->payload_algid == 0x89 && state->aes_key_loaded[0] == 1 ) || //P25 AES128
(state->currentslot == 0 && state->payload_algid == 0x84 && state->aes_key_loaded[0] == 1 ) || //P25 AES256
(state->currentslot == 0 && state->payload_algid == 0x36 && state->aes_key_loaded[0] == 1 ) || //KIRI ADV
(state->currentslot == 0 && state->payload_algid == 0x37 && state->aes_key_loaded[0] == 1 ) || //KIRI UNI
(state->currentslot == 0 && state->payload_algid >= 0x31 && \
state->payload_algid <= 0x3A && state->aes_key_loaded[0] == 1 ) || //KIRI Any
(state->currentslot == 0 && state->payload_algid == 0x02 && state->R != 0 ) ) //HYT ENHANCED
{
@@ -815,17 +815,11 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
n = 0;
hytera_enhanced_rc4_setup(opts, state, state->R, state->payload_mi);
}
if (state->payload_algid == 0x36)
if (state->payload_algid >= 0x31 && state->payload_algid <= 0x3A)
{
n = 0;
kirisun_adv_keystream_creation(state);
kirisun_keystream_creation(state);
}
if (state->payload_algid == 0x37)
{
n = 0;
kirisun_uni_keystream_creation(state);
}
//Load Keystream Octet Bytes directly into keystream array //TODO: Convert to unpack function
for (i = 0; i < 9 * 16; i++) //9 rounds at 16 octets
{
@@ -1285,8 +1279,8 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
(state->currentslot == 1 && state->payload_algidR == 0x25 && state->aes_key_loaded[1] == 1 ) || //DMR AES256
(state->currentslot == 1 && state->payload_algidR == 0x89 && state->aes_key_loaded[1] == 1 ) || //P25 AES128
(state->currentslot == 1 && state->payload_algidR == 0x84 && state->aes_key_loaded[1] == 1 ) || //P25 AES256
(state->currentslot == 1 && state->payload_algidR == 0x36 && state->aes_key_loaded[1] == 1 ) || //KIRI ADV
(state->currentslot == 1 && state->payload_algidR == 0x37 && state->aes_key_loaded[1] == 1 ) || //KIRI UNI
(state->currentslot == 1 && state->payload_algidR >= 0x31 && \
state->payload_algidR <= 0x3A && state->aes_key_loaded[1] == 1 ) || //KIRI Any
(state->currentslot == 1 && state->payload_algidR == 0x02 && state->RR != 0 ) ) //HYT ENHANCED
{
@@ -1321,17 +1315,11 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
n = 0;
hytera_enhanced_rc4_setup(opts, state, state->RR, state->payload_miR);
}
if (state->payload_algidR == 0x36)
if (state->payload_algidR >= 0x31 && state->payload_algidR <= 0x3A)
{
n = 0;
kirisun_adv_keystream_creation(state);
kirisun_keystream_creation(state);
}
if (state->payload_algidR == 0x37)
{
n = 0;
kirisun_uni_keystream_creation(state);
}
//Load Keystream Octet Bytes directly into keystream array
for (i = 0; i < 9 * 16; i++) //9 rounds at 16 octets //TODO: Convert to unpack function
{

View File

@@ -1125,26 +1125,13 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw(" Key: %010llX", state->R);
attron(COLOR_PAIR(3));
}
if (state->payload_algid == 0x36)
if (state->payload_algid >= 0x31 && state->payload_algid <= 0x3A)
{
attron(COLOR_PAIR(1));
printw("Kirisun Advanced ");
printw("Kirisun Encryption ");
if (state->aes_key_loaded[0] != 0) { printw("KS: %016llX ", state->A4[0]); }
attron(COLOR_PAIR(3));
}
if (state->payload_algid == 0x37)
{
attron(COLOR_PAIR(1));
printw("Kirisun Universal ");
if (state->aes_key_loaded[0] != 0) { printw("KS: %016llX ", state->A4[0]); }
attron(COLOR_PAIR(3));
}
if (state->payload_algid == 0x35)
{
attron(COLOR_PAIR(1));
printw("Kirisun Encryption "); //0x35 is a placeholder if gained through late-entry method and alg is not known
attron(COLOR_PAIR(3));
}
printw ("\n");
@@ -1327,26 +1314,13 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw(" Key: %010llX", state->RR);
attron(COLOR_PAIR(3));
}
if (state->payload_algidR == 0x36)
if (state->payload_algidR >= 0x31 && state->payload_algidR <= 0x3A)
{
attron(COLOR_PAIR(1));
printw("Kirisun Advanced ");
if (state->aes_key_loaded[1] != 0) { printw("KS: %016llX ", state->A4[1]); }
attron(COLOR_PAIR(3));
}
if (state->payload_algidR == 0x37)
{
attron(COLOR_PAIR(1));
printw("Kirisun Universal ");
if (state->aes_key_loaded[1] != 0) { printw("KS: %016llX ", state->A4[1]); }
attron(COLOR_PAIR(3));
}
if (state->payload_algidR == 0x35)
{
attron(COLOR_PAIR(1));
printw("Kirisun Encryption "); //0x35 is a placeholder if gained through late-entry method and alg is not known
attron(COLOR_PAIR(3));
}
printw ("\n");