diff --git a/include/dsd.h b/include/dsd.h index 99a91bf..bf3688e 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -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 diff --git a/src/1.c b/src/1.c index b125eef..1637ece 100644 --- a/src/1.c +++ b/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 * * - * - *-----------------------------------------------------------------------------*/ \ No newline at end of file + * + *-----------------------------------------------------------------------------*/ + +#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; + + } + +} \ No newline at end of file diff --git a/src/dmr_block.c b/src/dmr_block.c index 94ca583..cba29b5 100644 --- a/src/dmr_block.c +++ b/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