DMR: PDU RC4 and BP Decryption;

This commit is contained in:
lwvmobile
2025-02-23 02:58:45 -05:00
parent 035df461e1
commit 1725e45793
3 changed files with 215 additions and 4 deletions

View File

@@ -1456,6 +1456,11 @@ int m17_socket_receiver(dsd_opts * opts, void * data);
int udp_socket_connectM17(dsd_opts * opts, dsd_state * state);
int m17_socket_blaster(dsd_opts * opts, dsd_state * state, size_t nsam, void * data);
//RC4 function prototypes
void RC4(int drop, uint8_t keylength, uint8_t messagelength, uint8_t key[], uint8_t cipher[], uint8_t plain[]);
void rc4_block_output (int drop, int keylen, int meslen, uint8_t * key, uint8_t * output_blocks);
#ifdef __cplusplus
extern "C" {
#endif

52
src/1.c
View File

@@ -1,7 +1,53 @@
/*-------------------------------------------------------------------------------
* 1.c
* Placeholder File 1 -- This file is for temporary code storage
* RC4 and RC4 Block Output For Keystream Application
*
*
*
*-----------------------------------------------------------------------------*/
*
*-----------------------------------------------------------------------------*/
#include "dsd.h"
//this is for PDU usage
void rc4_block_output (int drop, int keylen, int meslen, uint8_t * key, uint8_t * output_blocks)
{
int i, j, x, count;
unsigned int keylength = (unsigned int)keylen;
unsigned int messagelength = (unsigned int)meslen;
unsigned int S[256];
for(i=0; i<256; i++)
S[i] = i;
j = 0;
for(i = 0; i<256; i++)
{
j = (j + S[i] + key[i % keylength]) % 256;
unsigned int temp = S[i];
S[i] = S[j];
S[j] = temp;
}
//Generate Keystream
i = 0;
j = 0;
x = 0;
unsigned int byte;
// fprintf (stderr, " Keystream Octets = ");
for(count = 0; count < (messagelength + drop); count++)
{
i = (i + 1) % 256;
j = (j + S[i]) % 256;
unsigned int temp = S[i];
S[i] = S[j];
S[j] = temp;
byte = S[(S[i] + S[j]) % 256];
//Collect Output blocks
if (count >= drop)
output_blocks[x++] = byte;
}
}

View File

@@ -8,6 +8,45 @@
#include "dsd.h"
#define DMR_PDU_DECRYPTION //disable to skip attempting to decrypt DMR PDUs
//just a bunch of BP keys, move to shared header later on or something
int BPK[256] = {
0x0000, 0x1F00, 0xE300, 0xFC00, 0x2503, 0x3A03, 0xC603, 0xD903,
0x4A05, 0x5505, 0xA905, 0xB605, 0x6F06, 0x7006, 0x8C06, 0x9306,
0x2618, 0x3918, 0xC518, 0xDA18, 0x031B, 0x1C1B, 0xE01B, 0xFF1B,
0x6C1D, 0x731D, 0x8F1D, 0x901D, 0x491E, 0x561E, 0xAA1E, 0xB51E,
0x4B28, 0x5428, 0xA828, 0xB728, 0x6E2B, 0x712B, 0x8D2B, 0x922B,
0x012D, 0x1E2D, 0xE22D, 0xFD2D, 0x242E, 0x3B2E, 0xC72E, 0xD82E,
0x6D30, 0x7230, 0x8E30, 0x9130, 0x4833, 0x5733, 0xAB33, 0xB433,
0x2735, 0x3835, 0xC435, 0xDB35, 0x0236, 0x1D36, 0xE136, 0xFE36,
0x2B49, 0x3449, 0xC849, 0xD749, 0x0E4A, 0x114A, 0xED4A, 0xF24A,
0x614C, 0xAE4C, 0x824C, 0x9D4C, 0x444F, 0x5B4F, 0xA74F, 0xB84F,
0x0D51, 0x1251, 0xEE51, 0xF151, 0x2852, 0x3752, 0xCB52, 0xD452,
0x4754, 0x5854, 0xA454, 0xBB54, 0x6257, 0x7D57, 0x8157, 0x9E57,
0x6061, 0x7F61, 0x8361, 0x9C61, 0x4562, 0x5A62, 0xA662, 0xB962,
0x2A64, 0x3564, 0xC964, 0xD664, 0x0F67, 0x1067, 0xEC67, 0xF367,
0x4679, 0x5979, 0xA579, 0xBA79, 0x637A, 0x7C7A, 0x807A, 0x9F7A,
0x0C7C, 0x137C, 0xEF7C, 0xF07C, 0x297F, 0x367F, 0xCA7F, 0xD57F,
0x4D89, 0x5289, 0xAE89, 0xB189, 0x688A, 0x778A, 0x8B8A, 0x948A,
0x078C, 0x188C, 0xE48C, 0xFB8C, 0x228F, 0x3D8F, 0xC18F, 0xDE8F,
0x6B91, 0x7491, 0x8891, 0x9791, 0x4E92, 0x5192, 0xAD92, 0xB292,
0x2194, 0x3E94, 0xC294, 0xDD94, 0x0497, 0x1B97, 0xE797, 0xF897,
0x06A1, 0x19A1, 0xE5A1, 0xFAA1, 0x23A2, 0x3CA2, 0xC0A2, 0xDFA2,
0x4CA4, 0x53A4, 0xAFA4, 0xB0A4, 0x69A7, 0x76A7, 0x8AA7, 0x95A7,
0x20B9, 0x3FB9, 0xC3B9, 0xDCB9, 0x05BA, 0x1ABA, 0xE6BA, 0xF9BA,
0x6ABC, 0x75BC, 0x89BC, 0x96BC, 0x4FBF, 0x50BF, 0xACBF, 0xB3BF,
0x66C0, 0x79C0, 0x85C0, 0x9AC0, 0x43C3, 0x5CC3, 0xA0C3, 0xBFC3,
0x2CC5, 0x33C5, 0xCFC5, 0xD0C5, 0x09C6, 0x16C6, 0xEAC6, 0xF5C6,
0x84D0, 0x85DF, 0x8AD3, 0x8BDC, 0xB6D5, 0xB7DA, 0xB8D6, 0xB9D9,
0xD0DA, 0xD1D5, 0xDED9, 0xDFD6, 0xE2DF, 0xE3D0, 0xECDC, 0xEDD3,
0x2DE8, 0x32E8, 0xCEE8, 0xD1E8, 0x08EB, 0x17EB, 0xEBEB, 0xF4EB,
0x67ED, 0x78ED, 0x84ED, 0x9BED, 0x42EE, 0x5DEE, 0xA1EE, 0xBEEE,
0x0BF0, 0x14F0, 0xE8F0, 0xF7F0, 0x2EF3, 0x31F3, 0xCDF3, 0xD2F3,
0x41F5, 0x5EF5, 0xA2F5, 0xBDF5, 0x64F6, 0x7BF6, 0x87F6, 0x98F6
};
//hopefully a more simplified (or logical) version...once you get past all the variables
void dmr_dheader (dsd_opts * opts, dsd_state * state, uint8_t dheader[], uint8_t dheader_bits[], uint32_t CRCCorrect, uint32_t IrrecoverableErrors)
{
@@ -824,6 +863,127 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
decrypted_pdu = 0;
}
//Start DMR Data PDU Decryption
#ifdef DMR_PDU_DECRYPTION
if (enc_check)
{
// decrypted_pdu = 0; //hasn't been decrypted yet
int poc = (int)state->data_block_poc[slot]; //say that three times real fast
int end = ((blocks+1)*block_len)-4-poc;
//sanity check on end, has to be a positive value
if (end < 0) end = 3096; //its a signed interger, so should reflect negative values here and not rollover
int alg = 0;
int kid = 0;
if (state->currentslot == 0)
alg = state->payload_algid;
else alg = state->payload_algidR;
if (state->currentslot == 0)
kid = state->payload_keyid;
else kid = state->payload_keyidR;
//test implementing RC4 decryption on Prop_PDU messages (quick and dirty)
uint8_t ob[129*24]; //may need more blocks (enough for 127 * 24)
uint8_t kiv[9]; UNUSED(kiv);
long int mi = 0;
unsigned long long int R = 0;
if (state->currentslot == 0)
mi = state->payload_mi;
else mi = state->payload_miR;
//mini key loader for RC4/DES
if (state->currentslot == 0)
R = state->rkey_array[state->payload_keyid];
else
R = state->rkey_array[state->payload_keyidR];
if (R == 0 && state->R != 0) R = state->R;
//easier to manually load up rather than make a loop (RC4)
kiv[0] = ((R & 0xFF00000000) >> 32);
kiv[1] = ((R & 0xFF000000) >> 24);
kiv[2] = ((R & 0xFF0000) >> 16);
kiv[3] = ((R & 0xFF00) >> 8);
kiv[4] = ((R & 0xFF) >> 0);
kiv[5] = ((mi & 0xFF000000) >> 24);
kiv[6] = ((mi & 0xFF0000) >> 16);
kiv[7] = ((mi & 0xFF00) >> 8);
kiv[8] = ((mi & 0xFF) >> 0);
//print alg/key and value if loaded
fprintf (stderr, "\n PDU ALG: %02X; Key ID: %02X;", alg, kid);
if (alg == 0) fprintf (stderr, " Moto BP;");
if (alg == 1) fprintf (stderr, " RC4;");
if (alg == 2) fprintf (stderr, " DES1;");
if (alg == 3) fprintf (stderr, " AES128;");
if (alg == 4) fprintf (stderr, " AES256;");
if (R && alg != 0) fprintf (stderr, " Key: %010llX;", R);
if (alg == 1 && R != 0) //RC4
{
rc4_block_output (256, 9, 3096, kiv, ob); //not sure if doing all 3096 is a good idea, lag?
decrypted_pdu = 1;
}
//NOTE: Observed that keystream should not be applied to pad bytes or CRC
//apply keystream here, only if alg is 1 or 4 AND key is available!
//using modulus 3096 to prevent sefgault (increased storage and changed ofb modes to a ptr)
//will want to rework output_blocks to be a pointer instead of a fixed size (done)
if (alg == 1 && R != 0)
{
for (i = 0; i < end; i++)
state->dmr_pdu_sf[slot][i] ^= ob[i%3096];
}
//BP key application
else if (alg == 0) //&& state->K != 0
{
//NOTE: using dmr_sr and dmr_soR now for a enc check on all encrypted PDUs
uint16_t bp_key = 0;
if (state->K != 0) //state->M == 1 &&
{
//load the BP key into the output blocks (only need two)
bp_key = BPK[state->K];
ob[0] = (bp_key >> 8) & 0xFF;
ob[1] = (bp_key >> 0) & 0xFF;
//
fprintf (stderr, " Key: %lld:%04X;", state->K, bp_key);
// fprintf (stderr, "ob1: %02X; ob2: %02X", ob[0], ob[1]);
}
if (bp_key != 0)
{
for (i = 0; i < end; i++)
state->dmr_pdu_sf[slot][i] ^= ob[i%2]; //modulus 2 here, just rinse and repeat
decrypted_pdu = 1;
}
}
//reset alg/keyid/mi after running?
if (state->currentslot == 0)
{
state->payload_mi = 0;
state->payload_algid = 0;
state->payload_keyid = 0;
state->dmr_so = 0;
}
else
{
state->payload_miR = 0;
state->payload_algidR = 0;
state->payload_keyidR = 0;
state->dmr_soR = 0;
}
} //end enc check
#endif
//End DMR Data PDU Decryption
//decode PDU
if (enc_check == 1 && decrypted_pdu == 0) //check for encryption and if it was decrypted first or not
{
@@ -875,7 +1035,7 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
}
//debug
fprintf (stderr, " CRC32: %08X / %08X", CRCExtracted, CRCComputed);
// fprintf (stderr, " CRC32: %08X / %08X", CRCExtracted, CRCComputed);
if (CRCCorrect) ; //print nothing
else