/* * Copyright (C) 2010 DSD Author * GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0) * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "dsd.h" //NOTE: This set of functions will be reorganized and simplified (hopefully) or at least //a more logical flow will be established to jive with the new audio handling void keyring(dsd_opts * opts, dsd_state * state) { UNUSED(opts); if (state->currentslot == 0) state->R = state->rkey_array[state->payload_keyid]; if (state->currentslot == 1) state->RR = state->rkey_array[state->payload_keyidR]; } void RC4(int drop, uint8_t keylength, uint8_t messagelength, uint8_t key[], uint8_t cipher[], uint8_t plain[]) { int i, j, count; uint8_t t, b; //init Sbox uint8_t S[256]; for(int i = 0; i < 256; i++) S[i] = i; //Key Scheduling j = 0; for(i = 0; i < 256; i++) { j = (j + S[i] + key[i % keylength]) % 256; t = S[i]; S[i] = S[j]; S[j] = t; } //Drop Bytes and Cipher Byte XOR i = j = 0; for(count = 0; count < (messagelength + drop); count++) { i = (i + 1) % 256; j = (j + S[i]) % 256; t = S[i]; S[i] = S[j]; S[j] = t; b = S[(S[i] + S[j]) % 256]; //return mbe payload byte here if (count >= drop) plain[count - drop] = b^cipher[count - drop]; } } int Pr[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, //31 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, //63 0x2B49, 0x3449, 0xC849, 0xD749, 0x0E4A, 0x114A, 0xED4A, 0xF24A, 0x614C, 0x7E4C, 0x824C, 0x9D4C, 0x444F, 0x5B4F, 0xA74F, 0xB84F, 0x0D51, 0x1251, 0xEE51, 0xF151, 0x2852, 0x3752, 0xCB52, 0xD452, 0x4754, 0x5854, 0xA454, 0xBB54, 0x6257, 0x7D57, 0x8157, 0x9E57, //95 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, //127 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, //159 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, //191 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, //223 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 //255 }; void playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv) { int i; char imbe_d[88]; char ambe_d[49]; for (i = state->optind; i < argc; i++) { sprintf (opts->mbe_in_file, "%s", argv[i]); openMbeInFile (opts, state); mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced); fprintf (stderr, "playing %s\n", opts->mbe_in_file); while (feof (opts->mbe_in_f) == 0) { if (state->mbe_file_type == 0) { readImbe4400Data (opts, state, imbe_d); mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); if (opts->audio_out == 1 && opts->floating_point == 0) { processAudio(opts, state); } if (opts->wav_out_f != NULL) { writeSynthesizedVoice (opts, state); } if (opts->audio_out == 1 && opts->floating_point == 0) { playSynthesizedVoiceMS (opts, state); } if (opts->floating_point == 1) { memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l)); playSynthesizedVoiceFM (opts, state); } } else if (state->mbe_file_type > 0) //ambe files { readAmbe2450Data (opts, state, ambe_d); int x; unsigned long long int k; if (state->K != 0) //apply Pr key { k = Pr[state->K]; k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k ); for (short int j = 0; j < 48; j++) //49 { x = ( ((k << j) & 0x800000000000) >> 47 ); ambe_d[j] ^= x; } } //ambe+2 if (state->mbe_file_type == 1) mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); //dstar ambe if (state->mbe_file_type == 2) mbe_processAmbe2400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); if (opts->audio_out == 1 && opts->floating_point == 0) { processAudio(opts, state); } if (opts->wav_out_f != NULL) { writeSynthesizedVoice (opts, state); } if (opts->audio_out == 1 && opts->floating_point == 0) { playSynthesizedVoiceMS (opts, state); } if (opts->floating_point == 1) { memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l)); playSynthesizedVoiceFM (opts, state); } } if (exitflag == 1) { cleanupAndExit (opts, state); } } } } void processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24]) { int i; char imbe_d[88]; char ambe_d[49]; unsigned long long int k; int x; //these conditions should ensure no clashing with the BP/HBP/Scrambler key loading machanisms already coded in if (state->currentslot == 0 && state->payload_algid != 0 && state->payload_algid != 0x80 && state->keyloader == 1) keyring (opts, state); if (state->currentslot == 1 && state->payload_algidR != 0 && state->payload_algidR != 0x80 && state->keyloader == 1) keyring (opts, state); //24-bit TG to 16-bit hash uint32_t hash = 0; uint8_t hash_bits[24]; memset (hash_bits, 0, sizeof(hash_bits)); int preempt = 0; //TDMA dual voice slot preemption(when using OSS output) for (i = 0; i < 88; i++) { imbe_d[i] = 0; } for (i = 0; i < 49; i++) { ambe_d[i] = 0; } //set playback mode for this frame char mode[8]; sprintf (mode, "%s", ""); //if we are using allow/whitelist mode, then write 'B' to mode for block //comparison below will look for an 'A' to write to mode if it is allowed if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B"); int groupNumber = 0; if (state->currentslot == 0) groupNumber = state->lasttg; else groupNumber = state->lasttgR; for (i = 0; i < state->group_tally; i++) { if (state->group_array[i].groupNumber == groupNumber) { strcpy (mode, state->group_array[i].groupMode); break; } } //set flag to not play audio this time, but won't prevent writing to wav files -- disabled for now // if (strcmp(mode, "B") == 0) opts->audio_out = 0; //causes a buzzing now (probably due to not running processAudio before the SS3 or SS4) //end set playback mode for this frame if ((state->synctype == 0) || (state->synctype == 1)) { // 0 +P25p1 // 1 -P25p1 state->errs = mbe_eccImbe7200x4400C0 (imbe_fr); state->errs2 = state->errs; mbe_demodulateImbe7200x4400Data (imbe_fr); state->errs2 += mbe_eccImbe7200x4400Data (imbe_fr, imbe_d); //P25p1 RC4 Handling if (state->payload_algid == 0xAA && state->R != 0) { uint8_t cipher[11] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t plain[11] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key 0x00, 0x00, 0x00, 0x00, 0x00, // <- MI 0x00, 0x00, 0x00}; // <- MI cont. //easier to manually load up rather than make a loop rckey[0] = ((state->R & 0xFF00000000) >> 32); rckey[1] = ((state->R & 0xFF000000) >> 24); rckey[2] = ((state->R & 0xFF0000) >> 16); rckey[3] = ((state->R & 0xFF00) >> 8); rckey[4] = ((state->R & 0xFF) >> 0); // load valid MI from state->payload_miP rckey[5] = ((state->payload_miP & 0xFF00000000000000) >> 56); rckey[6] = ((state->payload_miP & 0xFF000000000000) >> 48); rckey[7] = ((state->payload_miP & 0xFF0000000000) >> 40); rckey[8] = ((state->payload_miP & 0xFF00000000) >> 32); rckey[9] = ((state->payload_miP & 0xFF000000) >> 24); rckey[10] = ((state->payload_miP & 0xFF0000) >> 16); rckey[11] = ((state->payload_miP & 0xFF00) >> 8); rckey[12] = ((state->payload_miP & 0xFF) >> 0); // if (state->p25vc == 0) // { // fprintf (stderr, "%s", KYEL); // fprintf (stderr, "\n RC4K "); // for (short o = 0; o < 13; o++) // { // fprintf (stderr, "%02X", rckey[o]); // } // fprintf (stderr, "%s", KNRM); // } //load imbe_d into imbe_cipher octets int z = 0; for (i = 0; i < 11; i++) { cipher[i] = 0; plain[i] = 0; for (short int j = 0; j < 8; j++) { cipher[i] = cipher[i] << 1; cipher[i] = cipher[i] + imbe_d[z]; imbe_d[z] = 0; z++; } } RC4(state->dropL, 13, 11, rckey, cipher, plain); state->dropL += 11; z = 0; for (short p = 0; p < 11; p++) { for (short o = 0; o < 8; o++) { imbe_d[z] = (plain[p] & 0x80) >> 7; plain[p] = plain[p] << 1; z++; } } } mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); //mbe_processImbe7200x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); if (opts->payload == 1) { PrintIMBEData (opts, state, imbe_d); } //increment vc counter by one. state->p25vc++; if (opts->mbe_out_f != NULL && state->dmr_encL == 0) //only save if this bit not set { saveImbe4400Data (opts, state, imbe_d); } } else if ((state->synctype == 14) || (state->synctype == 15)) //pV Sync { state->errs = mbe_eccImbe7100x4400C0 (imbe7100_fr); state->errs2 = state->errs; mbe_demodulateImbe7100x4400Data (imbe7100_fr); state->errs2 += mbe_eccImbe7100x4400Data (imbe7100_fr, imbe_d); if (opts->payload == 1) { PrintIMBEData (opts, state, imbe_d); } mbe_convertImbe7100to7200(imbe_d); mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); if (opts->mbe_out_f != NULL) { saveImbe4400Data (opts, state, imbe_d); } } else if ((state->synctype == 6) || (state->synctype == 7)) { mbe_processAmbe3600x2400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); if (opts->payload == 1) { PrintAMBEData (opts, state, ambe_d); } if (opts->mbe_out_f != NULL) { saveAmbe2450Data (opts, state, ambe_d); } } else if ((state->synctype == 28) || (state->synctype == 29)) //was 8 and 9 { state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr); state->errs2 = state->errs; mbe_demodulateAmbe3600x2450Data (ambe_fr); state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d); if ( (state->nxdn_cipher_type == 0x01 && state->R > 0) || (state->M == 1 && state->R > 0) ) { if (state->payload_miN == 0) { state->payload_miN = state->R; } char ambe_temp[49]; for (short int i = 0; i < 49; i++) { ambe_temp[i] = ambe_d[i]; ambe_d[i] = 0; } LFSRN(ambe_temp, ambe_d, state); } mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); if (opts->payload == 1) { PrintAMBEData (opts, state, ambe_d); } if (opts->mbe_out_f != NULL && (state->dmr_encL == 0 || opts->dmr_mute_encL == 0) ) { saveAmbe2450Data (opts, state, ambe_d); } } else { //stereo slots and slot 0 (left slot) if (state->currentslot == 0) //&& opts->dmr_stereo == 1 { state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr); state->errs2 = state->errs; mbe_demodulateAmbe3600x2450Data (ambe_fr); state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d); //EXPERIMENTAL!! //load basic privacy key number from array by the tg value (if not forced) //currently only Moto BP and Hytera 10 Char BP if (state->M == 0 && state->payload_algid == 0) { //see if we need to hash a value larger than 16-bits hash = state->lasttg & 0xFFFFFF; // fprintf (stderr, "TG: %lld Hash: %ld ", state->lasttg, hash); if (hash > 0xFFFF) //if greater than 16-bits { for (int i = 0; i < 24; i++) { hash_bits[i] = ((hash << i) & 0x800000) >> 23; //load into array for CRC16 } hash = ComputeCrcCCITT16d (hash_bits, 24); hash = hash & 0xFFFF; //make sure its no larger than 16-bits // fprintf (stderr, "Hash: %d ", hash); } if (state->rkey_array[hash] != 0) { state->K = state->rkey_array[hash] & 0xFF; //doesn't exceed 255 state->K1 = state->H = state->rkey_array[hash] & 0xFFFFFFFFFF; //doesn't exceed 40-bit limit opts->dmr_mute_encL = 0; // fprintf (stderr, "Key: %X ", state->rkey_array[hash]); } // else opts->dmr_mute_encL = 1; //may cause issues for manual key entry (non-csv) } if ( (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x10) || (state->K > 0 && state->M == 1) ) { k = Pr[state->K]; k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k ); for (short int j = 0; j < 48; j++) //49 { x = ( ((k << j) & 0x800000000000) >> 47 ); ambe_d[j] ^= x; } } if ( (state->K1 > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x68) || (state->K1 > 0 && state->M == 1) ) { int pos = 0; unsigned long long int k1 = state->K1; unsigned long long int k2 = state->K2; unsigned long long int k3 = state->K3; unsigned long long int k4 = state->K4; int T_Key[256] = {0}; int pN[882] = {0}; int len = 0; if (k2 == 0) { len = 39; k1 = k1 << 24; } if (k2 != 0) { len = 127; } if (k4 != 0) { len = 255; } for (i = 0; i < 64; i++) { T_Key[i] = ( ((k1 << i) & 0x8000000000000000) >> 63 ); T_Key[i+64] = ( ((k2 << i) & 0x8000000000000000) >> 63 ); T_Key[i+128] = ( ((k3 << i) & 0x8000000000000000) >> 63 ); T_Key[i+192] = ( ((k4 << i) & 0x8000000000000000) >> 63 ); } for (i = 0; i < 882; i++) { pN[i] = T_Key[pos]; pos++; if (pos > len) { pos = 0; } } //sanity check if (state->DMRvcL > 17) //18 { state->DMRvcL = 17; //18 } pos = state->DMRvcL * 49; for(i = 0; i < 49; i++) { ambe_d[i] ^= pN[pos]; pos++; } state->DMRvcL++; } //DMR RC4, Slot 1 if (state->currentslot == 0 && state->payload_algid == 0x21 && state->R != 0) { uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t rckey[9] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key 0x00, 0x00, 0x00, 0x00}; // <- MI //easier to manually load up rather than make a loop rckey[0] = ((state->R & 0xFF00000000) >> 32); rckey[1] = ((state->R & 0xFF000000) >> 24); rckey[2] = ((state->R & 0xFF0000) >> 16); rckey[3] = ((state->R & 0xFF00) >> 8); rckey[4] = ((state->R & 0xFF) >> 0); rckey[5] = ((state->payload_mi & 0xFF000000) >> 24); rckey[6] = ((state->payload_mi & 0xFF0000) >> 16); rckey[7] = ((state->payload_mi & 0xFF00) >> 8); rckey[8] = ((state->payload_mi & 0xFF) >> 0); //pack cipher byte array from ambe_d bit array pack_ambe(ambe_d, cipher, 49); //only run keystream application if errs < 3 -- this is a fix to the pop sound //that may occur on some systems that preempt VC6 voice for a RC opportuninity (TXI) //this occurs because we are supposed to either have a a 'repeat' frame, or 'silent' frame play //due to the error, but the keystream application makes it random 'pfft pop' sound instead if (state->errs < 3) RC4(state->dropL, 9, 7, rckey, cipher, plain); else memcpy (plain, cipher, sizeof(plain)); state->dropL += 7; //unpack deciphered plain array back into ambe_d bit array memset (ambe_d, 0, 49*sizeof(char)); unpack_ambe(plain, ambe_d); } //P25p2 RC4 Handling, VCH 0 if (state->currentslot == 0 && state->payload_algid == 0xAA && state->R != 0 && ((state->synctype == 35) || (state->synctype == 36))) { uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key 0x00, 0x00, 0x00, 0x00, 0x00, // <- MI 0x00, 0x00, 0x00}; // <- MI cont. //easier to manually load up rather than make a loop rckey[0] = ((state->R & 0xFF00000000) >> 32); rckey[1] = ((state->R & 0xFF000000) >> 24); rckey[2] = ((state->R & 0xFF0000) >> 16); rckey[3] = ((state->R & 0xFF00) >> 8); rckey[4] = ((state->R & 0xFF) >> 0); // load valid MI from state->payload_miP rckey[5] = ((state->payload_miP & 0xFF00000000000000) >> 56); rckey[6] = ((state->payload_miP & 0xFF000000000000) >> 48); rckey[7] = ((state->payload_miP & 0xFF0000000000) >> 40); rckey[8] = ((state->payload_miP & 0xFF00000000) >> 32); rckey[9] = ((state->payload_miP & 0xFF000000) >> 24); rckey[10] = ((state->payload_miP & 0xFF0000) >> 16); rckey[11] = ((state->payload_miP & 0xFF00) >> 8); rckey[12] = ((state->payload_miP & 0xFF) >> 0); //pack cipher byte array from ambe_d bit array pack_ambe(ambe_d, cipher, 49); RC4(state->dropL, 13, 7, rckey, cipher, plain); state->dropL += 7; //unpack deciphered plain array back into ambe_d bit array memset (ambe_d, 0, 49*sizeof(char)); unpack_ambe(plain, ambe_d); } mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); //old method for this step below //mbe_processAmbe3600x2450Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); if (opts->payload == 1) // && state->R == 0 this is why slot 1 didn't primt abme, probably had it set during testing { PrintAMBEData (opts, state, ambe_d); } //restore MBE file save, slot 1 -- consider saving even if enc if (opts->mbe_out_f != NULL && (state->dmr_encL == 0 || opts->dmr_mute_encL == 0) ) { saveAmbe2450Data (opts, state, ambe_d); } } //stereo slots and slot 1 (right slot) if (state->currentslot == 1) //&& opts->dmr_stereo == 1 { state->errsR = mbe_eccAmbe3600x2450C0 (ambe_fr); state->errs2R = state->errsR; mbe_demodulateAmbe3600x2450Data (ambe_fr); state->errs2R += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d); //EXPERIMENTAL!! //load basic privacy key number from array by the tg value (if not forced) //currently only Moto BP and Hytera 10 Char BP if (state->M == 0 && state->payload_algidR == 0) { //see if we need to hash a value larger than 16-bits hash = state->lasttgR & 0xFFFFFF; // fprintf (stderr, "TG: %lld Hash: %ld ", state->lasttgR, hash); if (hash > 0xFFFF) //if greater than 16-bits { for (int i = 0; i < 24; i++) { hash_bits[i] = ((hash << i) & 0x800000) >> 23; //load into array for CRC16 } hash = ComputeCrcCCITT16d (hash_bits, 24); hash = hash & 0xFFFF; //make sure its no larger than 16-bits // fprintf (stderr, "Hash: %d ", hash); } if (state->rkey_array[hash] != 0) { state->K = state->rkey_array[hash] & 0xFF; //doesn't exceed 255 state->K1 = state->H = state->rkey_array[hash] & 0xFFFFFFFFFF; //doesn't exceed 40-bit limit opts->dmr_mute_encR = 0; // fprintf (stderr, "Key: %X ", state->rkey_array[hash]); } // else opts->dmr_mute_encR = 1; //may cause issues for manual key entry (non-csv) } if ( (state->K > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0 && state->dmr_fidR == 0x10) || (state->K > 0 && state->M == 1) ) { k = Pr[state->K]; k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k ); for (short int j = 0; j < 48; j++) { x = ( ((k << j) & 0x800000000000) >> 47 ); ambe_d[j] ^= x; } } if ( (state->K1 > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0 && state->dmr_fidR == 0x68) || (state->K1 > 0 && state->M == 1)) { int pos = 0; unsigned long long int k1 = state->K1; unsigned long long int k2 = state->K2; unsigned long long int k3 = state->K3; unsigned long long int k4 = state->K4; int T_Key[256] = {0}; int pN[882] = {0}; int len = 0; if (k2 == 0) { len = 39; k1 = k1 << 24; } if (k2 != 0) { len = 127; } if (k4 != 0) { len = 255; } for (i = 0; i < 64; i++) { T_Key[i] = ( ((k1 << i) & 0x8000000000000000) >> 63 ); T_Key[i+64] = ( ((k2 << i) & 0x8000000000000000) >> 63 ); T_Key[i+128] = ( ((k3 << i) & 0x8000000000000000) >> 63 ); T_Key[i+192] = ( ((k4 << i) & 0x8000000000000000) >> 63 ); } for (i = 0; i < 882; i++) { pN[i] = T_Key[pos]; pos++; if (pos > len) { pos = 0; } } //sanity check if (state->DMRvcR > 17) //18 { state->DMRvcR = 17; //18 } pos = state->DMRvcR * 49; for(i = 0; i < 49; i++) { ambe_d[i] ^= pN[pos]; pos++; } state->DMRvcR++; } //DMR RC4, Slot 2 if (state->currentslot == 1 && state->payload_algidR == 0x21 && state->RR != 0) { uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t rckey[9] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key 0x00, 0x00, 0x00, 0x00}; // <- MI //easier to manually load up rather than make a loop rckey[0] = ((state->RR & 0xFF00000000) >> 32); rckey[1] = ((state->RR & 0xFF000000) >> 24); rckey[2] = ((state->RR & 0xFF0000) >> 16); rckey[3] = ((state->RR & 0xFF00) >> 8); rckey[4] = ((state->RR & 0xFF) >> 0); rckey[5] = ((state->payload_miR & 0xFF000000) >> 24); rckey[6] = ((state->payload_miR & 0xFF0000) >> 16); rckey[7] = ((state->payload_miR & 0xFF00) >> 8); rckey[8] = ((state->payload_miR & 0xFF) >> 0); //pack cipher byte array from ambe_d bit array pack_ambe(ambe_d, cipher, 49); //only run keystream application if errs < 3 -- this is a fix to the pop sound //that may occur on some systems that preempt VC6 voice for a RC opportuninity (TXI) //this occurs because we are supposed to either have a a 'repeat' frame, or 'silent' frame play //due to the error, but the keystream application makes it random 'pfft pop' sound instead if (state->errsR < 3) RC4(state->dropR, 9, 7, rckey, cipher, plain); else memcpy (plain, cipher, sizeof(plain)); state->dropR += 7; //unpack deciphered plain array back into ambe_d bit array memset (ambe_d, 0, 49*sizeof(char)); unpack_ambe(plain, ambe_d); } //P25p2 RC4 Handling, VCH 1 if (state->currentslot == 1 && state->payload_algidR == 0xAA && state->RR != 0 && ((state->synctype == 35) || (state->synctype == 36))) { uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key 0x00, 0x00, 0x00, 0x00, 0x00, // <- MI 0x00, 0x00, 0x00}; // <- MI cont. //easier to manually load up rather than make a loop rckey[0] = ((state->RR & 0xFF00000000) >> 32); rckey[1] = ((state->RR & 0xFF000000) >> 24); rckey[2] = ((state->RR & 0xFF0000) >> 16); rckey[3] = ((state->RR & 0xFF00) >> 8); rckey[4] = ((state->RR & 0xFF) >> 0); //state->payload_miN for VCH1/slot 2 rckey[5] = ((state->payload_miN & 0xFF00000000000000) >> 56); rckey[6] = ((state->payload_miN & 0xFF000000000000) >> 48); rckey[7] = ((state->payload_miN & 0xFF0000000000) >> 40); rckey[8] = ((state->payload_miN & 0xFF00000000) >> 32); rckey[9] = ((state->payload_miN & 0xFF000000) >> 24); rckey[10] = ((state->payload_miN & 0xFF0000) >> 16); rckey[11] = ((state->payload_miN & 0xFF00) >> 8); rckey[12] = ((state->payload_miN & 0xFF) >> 0); //pack cipher byte array from ambe_d bit array pack_ambe(ambe_d, cipher, 49); RC4(state->dropR, 13, 7, rckey, cipher, plain); state->dropR += 7; //unpack deciphered plain array back into ambe_d bit array memset (ambe_d, 0, 49*sizeof(char)); unpack_ambe(plain, ambe_d); } mbe_processAmbe2450Dataf (state->audio_out_temp_bufR, &state->errsR, &state->errs2R, state->err_strR, ambe_d, state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2, opts->uvquality); //old method for this step below //mbe_processAmbe3600x2450Framef (state->audio_out_temp_bufR, &state->errsR, &state->errs2R, state->err_strR, ambe_fr, ambe_d, state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2, opts->uvquality); if (opts->payload == 1) { PrintAMBEData (opts, state, ambe_d); } //restore MBE file save, slot 2 -- consider saving even if enc if (opts->mbe_out_fR != NULL && (state->dmr_encR == 0 || opts->dmr_mute_encR == 0) ) { saveAmbe2450DataR (opts, state, ambe_d); } } //X2-TDMA? Not sure what still makes it this far to run under Framef // if (opts->dmr_stereo == 0) // { // mbe_processAmbe3600x2450Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality); // if (opts->payload == 1) // { // PrintAMBEData (opts, state, ambe_d); // } // //only save MBE files if not enc or unmuted, THIS does not seem to work for some reason // if (opts->mbe_out_f != NULL && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0) ) // { // saveAmbe2450Data (opts, state, ambe_d); // } // } } //quick enc check to determine whether or not to play enc traffic int enc_bit = 0; //end enc check if ( (opts->dmr_mono == 1 || opts->dmr_stereo == 1) && state->currentslot == 0) //all mono traffic routed through 'left' { enc_bit = (state->dmr_so >> 6) & 0x1; if (enc_bit == 1) { state->dmr_encL = 1; } //checkdown for P25 1 and 2 else if (state->payload_algid != 0 && state->payload_algid != 0x80) { state->dmr_encL = 1; } else state->dmr_encL = 0; //check for available R key if (state->R != 0) state->dmr_encL = 0; //second checkdown for P25p2 WACN, SYSID, and CC set if (state->synctype == 35 || state->synctype == 36) { if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0) { state->dmr_encL = 1; } } //reverse mute testing, only mute unencrypted traffic (slave piggyback dsd+ method) if (opts->reverse_mute == 1) { if (state->dmr_encL == 0) { state->dmr_encL = 1; opts->unmute_encrypted_p25 = 0; opts->dmr_mute_encL = 1; } else { state->dmr_encL = 0; opts->unmute_encrypted_p25 = 1; opts->dmr_mute_encL = 0; } } //end reverse mute test //OSS 48k/1 Specific Voice Preemption if dual voices on TDMA and one slot has preference over the other if (opts->slot_preference == 1 && opts->audio_out_type == 5 && opts->audio_out == 1 && (state->dmrburstR == 16 || state->dmrburstR == 21) ) { opts->audio_out = 0; preempt = 1; if (opts->payload == 0 && opts->slot1_on == 1) fprintf (stderr, " *MUTED*"); else if (opts->payload == 0 && opts->slot1_on == 0) fprintf (stderr, " *OFF*"); } state->debug_audio_errors += state->errs2; if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0) { if ( opts->floating_point == 0 ) //opts->audio_out == 1 && //needed to remove for AERO OSS so we could still save wav files during dual voices { #ifdef AERO_BUILD if(opts->audio_out == 1 && opts->slot1_on == 1) //add conditional check here, otherwise some lag occurs on dual voices with OSS48k/1 input due to buffered audio #endif processAudio(opts, state); } if (opts->audio_out == 1 && opts->floating_point == 0 && opts->audio_out_type == 5 && opts->slot1_on == 1) //for OSS 48k 1 channel configs -- relocate later if possible { playSynthesizedVoiceMS (opts, state); //it may be more beneficial to move this to each individual decoding type to handle, but ultimately, let's just simpifly mbe handling instead } } memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l)); //these are for mono or FDMA where we don't need to buffer and wait for a stereo mix } if (opts->dmr_stereo == 1 && state->currentslot == 1) { enc_bit = (state->dmr_soR >> 6) & 0x1; if (enc_bit == 0x1) { state->dmr_encR = 1; } //checkdown for P25 1 and 2 else if (state->payload_algidR != 0 && state->payload_algidR != 0x80) { state->dmr_encR = 1; } else state->dmr_encR = 0; //check for available RR key if (state->RR != 0) state->dmr_encR = 0; //second checkdown for P25p2 WACN, SYSID, and CC set if (state->synctype == 35 || state->synctype == 36) { if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0) { state->dmr_encR = 1; } } //reverse mute testing, only mute unencrypted traffic (slave piggyback dsd+ method) if (opts->reverse_mute == 1) { if (state->dmr_encR == 0) { state->dmr_encR = 1; opts->unmute_encrypted_p25 = 0; opts->dmr_mute_encR = 1; } else { state->dmr_encR = 0; opts->unmute_encrypted_p25 = 1; opts->dmr_mute_encR = 0; } } //end reverse mute test //OSS 48k/1 Specific Voice Preemption if dual voices on TDMA and one slot has preference over the other if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && (state->dmrburstL == 16 || state->dmrburstL == 21) ) { opts->audio_out = 0; preempt = 1; if (opts->payload == 0 && opts->slot2_on == 1) fprintf (stderr, " *MUTED*"); else if (opts->payload == 0 && opts->slot2_on == 0) fprintf (stderr, " *OFF*"); } state->debug_audio_errorsR += state->errs2R; if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0) { if ( opts->floating_point == 0) //opts->audio_out == 1 && //needed to remove for AERO OSS so we could still save wav files during dual voices { #ifdef AERO_BUILD if(opts->audio_out == 1 && opts->slot2_on == 1) //add conditional check here, otherwise some lag occurs on dual voices with OSS48k/1 input due to buffered audio #endif processAudioR(opts, state); } if (opts->audio_out == 1 && opts->floating_point == 0 && opts->audio_out_type == 5 && opts->slot2_on == 1) //for OSS 48k 1 channel configs -- relocate later if possible { playSynthesizedVoiceMSR (opts, state); } } memcpy (state->f_r, state->audio_out_temp_bufR, sizeof(state->f_r)); } //if using anything but DMR Stereo, borrowing state->dmr_encL to signal enc or clear for other types if (opts->dmr_mono == 0 && opts->dmr_stereo == 0 && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0) ) { state->debug_audio_errors += state->errs2; if (opts->audio_out == 1 && opts->floating_point == 0 ) //&& opts->pulse_digi_rate_out == 8000 { processAudio(opts, state); } // if (opts->audio_out == 1) // { // playSynthesizedVoice (opts, state); // } memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l)); //P25p1 FDMA 8k/1 channel -f1 switch } //if using anything but DMR Stereo, borrowing state->dmr_encL to signal enc or clear for other types if (opts->wav_out_f != NULL && opts->dmr_stereo == 0 && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0)) { writeSynthesizedVoice (opts, state); } //per call can only be used when ncurses terminal is active since we use its call history matrix for when to record if (opts->dmr_stereo_wav == 1 && opts->dmr_stereo == 1 && state->currentslot == 0) //opts->use_ncurses_terminal == 1 && { if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0) { //write wav to per call on left channel Slot 1 writeSynthesizedVoice (opts, state); } } //per call can only be used when ncurses terminal is active since we use its call history matrix for when to record if (opts->dmr_stereo_wav == 1 && opts->dmr_stereo == 1 && state->currentslot == 1) //opts->use_ncurses_terminal == 1 && { if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0) { //write wav to per call on right channel Slot 2 writeSynthesizedVoiceR (opts, state); } } if (preempt == 1) { opts->audio_out = 1; preempt = 0; } //reset audio out flag for next repitition --disabled for now // if (strcmp(mode, "B") == 0) opts->audio_out = 1; //restore flag for null output type if (opts->audio_out_type == 9) opts->audio_out = 0; }