mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 01:07:24 -05:00
DMR: PDU RC4 and BP Decryption;
This commit is contained in:
@@ -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
52
src/1.c
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
162
src/dmr_block.c
162
src/dmr_block.c
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user