diff --git a/include/dsd.h b/include/dsd.h index 85bea6c..0ae97e5 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -1622,6 +1622,11 @@ void aes_ctr_bitwise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * paylo //Tytera Encryption Modes void tyt16_ambe2_codeword_keystream(dsd_state * state, char ambe_fr[4][24], int fnum); +void tyt_ep_aes_keystream_creation(dsd_state * state, char * input); +void tyt_ap_pc4_keystream_creation(dsd_state * state, char * input); + +//Misc Other Encryption Modes +void ken_dmr_scrambler_keystream_creation(dsd_state * state, char * input); //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); diff --git a/src/crypt-etc.c b/src/crypt-etc.c new file mode 100644 index 0000000..a0a0782 --- /dev/null +++ b/src/crypt-etc.c @@ -0,0 +1,31 @@ +#include "dsd.h" + +void ken_dmr_scrambler_keystream_creation(dsd_state * state, char * input) +{ + /* + SLOT 1 Protected LC FLCO=0x00 FID=0x20 <--this link appears to indicate scrambler usage from Kenwood on DMR + DMR PDU Payload [80][20][40][00][00][01][00][00][01] SB: 00000000000 - 000; + + SLOT 1 TGT=1 SRC=1 FLCO=0x00 FID=0x00 SVC=0x00 Group Call <--different call, no scrambler from same Kenwood Radio + DMR PDU Payload [00][00][00][00][00][01][00][00][01] + + For This, we could possible transition this to not be enforced + since we may have a positive indicator in link control, + but needs further samples and validation + */ + + int lfsr = 0, bit = 0; + sscanf (input, "%d", &lfsr); + fprintf (stderr,"DMR Kenwood 15-bit Scrambler Key %05d with Forced Application\n", lfsr); + + for (int i = 0; i < 882; i++) + { + state->static_ks_bits[0][i] = lfsr & 0x1; + state->static_ks_bits[1][i] = lfsr & 0x1; + bit = ( (lfsr >> 1) ^ (lfsr >> 0) ) & 1; + lfsr = ( (lfsr >> 1 ) | (bit << 14) ); + } + + state->ken_sc = 1; + +} \ No newline at end of file diff --git a/src/crypt-tyt.c b/src/crypt-tyt.c index e820d16..2e56f60 100644 --- a/src/crypt-tyt.c +++ b/src/crypt-tyt.c @@ -1,7 +1,8 @@ #include "dsd.h" #include "dmr_const.h" +#include "pc4.h" -//interleaved code words for AMBE+2 +//interleaved code words for AMBE+2 (as it arrives over the air) void ambe2_codeword_print_i (dsd_opts * opts, char ambe_fr[4][24]) { uint8_t interleaved[72]; @@ -94,8 +95,8 @@ void ambe2_codeword_print_f (dsd_opts * opts, char ambe_fr[4][24]) } -//tested working perfectly fine on some Tytera BP samples, but not on others -//is there two or more different Tytera (or CCR) BP modes depending on FW? +//NOTE: This mode DOES NOT work over a repeater, simplex only +//repeaters may or will attempt to correct the frame errors void tyt16_ambe2_codeword_keystream(dsd_state * state, char ambe_fr[4][24], int fnum) { @@ -154,4 +155,87 @@ void tyt16_ambe2_codeword_keystream(dsd_state * state, char ambe_fr[4][24], int z++; } +} + +void tyt_ap_pc4_keystream_creation(dsd_state * state, char * input) +{ + unsigned char key1[16] = {0}; + unsigned char key2[16] = {0}; + + char buf[1024]; + strncpy(buf, input, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + + char *pEnd; + uint64_t K1 = strtoull(buf, &pEnd, 16); + uint64_t K2 = strtoull(pEnd, &pEnd, 16); + + u64_to_bytes_be(K1, &key1[0]); + u64_to_bytes_be(K2, &key1[8]); + + for (int i=0;i<16;i++) key2[i] = key1[15-i]; + + /* Create key schedule */ + create_keys(&ctx, key2, sizeof(key2)); + ctx.rounds = nbround; + + fprintf (stderr,"DMR TYT AP (PC4) 128-bit Key %016llX%016llX with Forced Application\n", (unsigned long long int)K1, (unsigned long long int)K2); + state->tyt_ap = 1; + +} + +void tyt_ep_aes_keystream_creation(dsd_state * state, char * input) +{ + char buf[1024]; + strncpy(buf, input, 1023); + buf[1023] = '\0'; + + char *pEnd; + unsigned long long int K1 = strtoull (buf, &pEnd, 16); + unsigned long long int K2 = strtoull (pEnd, &pEnd, 16); + + // + uint8_t static_key[32]; + memset(static_key, 0, sizeof(static_key)); + + //static key value + static_key[0]=0x6e; static_key[1]=0x02; static_key[2]=0x8d; static_key[3]=0x8a; + static_key[4]=0xca; static_key[5]=0xeb; static_key[6]=0x9b; static_key[7]=0xbe; + static_key[8]=0x42; static_key[9]=0x72; static_key[10]=0xfb; static_key[11]=0x82; + static_key[12]=0x64; static_key[13]=0x56; static_key[14]=0x31; static_key[15]=0xfa; + + //the key value provided by user + uint8_t user_key[16]; + memset(user_key, 0, sizeof(user_key)); + + //Load user key into array to manipulate + for (int i = 0; i < 8; i++) + { + user_key[i+0] = (K1 >> (56-(i*8))) & 0xFF; + user_key[i+8] = (K2 >> (56-(i*8))) & 0xFF; + } + + uint8_t input_register[16]; + memset(input_register, 0, sizeof(input_register)); + + //manipulate user provided key by loading bytes in reverse order into the input_register + for (int i = 0; i < 16; i++) + input_register[15-i] = user_key[i]; + + uint8_t ks_bytes[16]; + memset(ks_bytes, 0, sizeof(ks_bytes)); + + //create keystream + aes_ofb_keystream_output(input_register, static_key, ks_bytes, 0, 1); + uint8_t ks_bits[128]; + memset(ks_bits, 0, sizeof(ks_bits)); + unpack_byte_array_into_bit_array(ks_bytes, ks_bits, 16); + + //load static keystream into ctx.bits since that isn't ever zeroed out + for (int i = 0; i < 49; i++) + ctx.bits[i] = ks_bits[i]; + + fprintf (stderr,"DMR TYT EP (AES-128) Key %016llX%016llX with Forced Application\n", K1, K2); + state->tyt_ep = 1; + } \ No newline at end of file diff --git a/src/dsd_main.c b/src/dsd_main.c index 47fd2e2..798ba5e 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -25,7 +25,6 @@ #include "dmr_const.h" #include "provoice_const.h" #include "git_ver.h" - #include "pc4.h" #include @@ -34,30 +33,6 @@ #endif volatile uint8_t exitflag; //fix for issue #136 - - void tyt_ap_init() - { - unsigned char key1[16] = {0}; - unsigned char key2[16] = {0}; - - char buf[1024]; - strncpy(buf, optarg, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\0'; - - char *pEnd; - uint64_t K1 = strtoull(buf, &pEnd, 16); - uint64_t K2 = strtoull(pEnd, &pEnd, 16); - - u64_to_bytes_be(K1, &key1[0]); - u64_to_bytes_be(K2, &key1[8]); - - for (int i=0;i<16;i++) key2[i] = key1[15-i]; - - /* Create key schedule */ - create_keys(&ctx, key2, sizeof(key2)); - ctx.rounds = nbround; - - } void handler(int sgnl) { @@ -2003,89 +1978,17 @@ //get user TYT AP Key and Force Its application case '!': - tyt_ap_init(); - state.tyt_ap = 1; - fprintf (stderr,"DMR TYT AP (PC4) 128-bit Key with Forced Application\n"); + tyt_ap_pc4_keystream_creation(&state, optarg); break; //get user TYT EP Key and Force Its application case '5': - //TODO: This, or combine with above with -! AP:KEY or EP:KEY (or similar) - strncpy(opts.szNumbers, optarg, 1023); - opts.szNumbers[1023] = '\0'; - unsigned long long int K1 = strtoull (opts.szNumbers, &pEnd, 16); - unsigned long long int K2 = strtoull (pEnd, &pEnd, 16); - uint8_t static_key[32]; - memset(static_key, 0, sizeof(static_key)); - - //static key value - static_key[0]=0x6e; static_key[1]=0x02; static_key[2]=0x8d; static_key[3]=0x8a; - static_key[4]=0xca; static_key[5]=0xeb; static_key[6]=0x9b; static_key[7]=0xbe; - static_key[8]=0x42; static_key[9]=0x72; static_key[10]=0xfb; static_key[11]=0x82; - static_key[12]=0x64; static_key[13]=0x56; static_key[14]=0x31; static_key[15]=0xfa; - - //the key value provided by user - uint8_t user_key[16]; - memset(user_key, 0, sizeof(user_key)); - - //Load user key into array to manipulate - for (int i = 0; i < 8; i++) - { - user_key[i+0] = (K1 >> (56-(i*8))) & 0xFF; - user_key[i+8] = (K2 >> (56-(i*8))) & 0xFF; - } - - uint8_t input_register[16]; - memset(input_register, 0, sizeof(input_register)); - - //manipulate user provided key by loading bytes in reverse order into the input_register - for (int i = 0; i < 16; i++) - input_register[15-i] = user_key[i]; - - uint8_t ks_bytes[16]; - memset(ks_bytes, 0, sizeof(ks_bytes)); - - //NOTE: To clarify, TYT EP uses ECB mode with the user key as input_register and the static key in the - //forward (encryption) direction, but we are calling OFB mode because the first round is the - //same concept and we only need the first round output, OFB is easier to use anyways. - - //create keystream - aes_ofb_keystream_output(input_register, static_key, ks_bytes, 0, 1); - uint8_t ks_bits[128]; - memset(ks_bits, 0, sizeof(ks_bits)); - unpack_byte_array_into_bit_array(ks_bytes, ks_bits, 16); - - //load static keystream into ctx.bits since that isn't ever zeroed out - for (int i = 0; i < 49; i++) - ctx.bits[i] = ks_bits[i]; - fprintf (stderr,"DMR TYT EP (AES-128) Key %016llX%016llX with Forced Application\n", K1, K2); - state.tyt_ep = 1; + tyt_ep_aes_keystream_creation(&state, optarg); break; + //get user Kenwood DMR Scrambler Key case '9': - /* - SLOT 1 Protected LC FLCO=0x00 FID=0x20 <--this link appears to indicate scrambler usage from Kenwood on DMR - DMR PDU Payload [80][20][40][00][00][01][00][00][01] SB: 00000000000 - 000; - - SLOT 1 TGT=1 SRC=1 FLCO=0x00 FID=0x00 SVC=0x00 Group Call <--same call, but no scrambler on same Kenwood Radio - DMR PDU Payload [00][00][00][00][00][01][00][00][01] - - For This, we could possible transition this to not be enforced - since we may have a positive indicator in link control, - but needs further samples and validation - */ - int lfsr = 0, bit = 0; - sscanf (optarg, "%d", &lfsr); - fprintf (stderr,"DMR Kenwood 15-bit Scrambler Key %05d with Forced Application\n", lfsr); - for (int i = 0; i < 882; i++) - { - state.static_ks_bits[0][i] = lfsr & 0x1; - state.static_ks_bits[1][i] = lfsr & 0x1; - bit = ( (lfsr >> 1) ^ (lfsr >> 0) ) & 1; - lfsr = ( (lfsr >> 1 ) | (bit << 14) ); - } - - state.ken_sc = 1; + ken_dmr_scrambler_keystream_creation(&state, optarg); break; case '3': @@ -3193,36 +3096,6 @@ fprintf (stderr, "Expecting inverted M17 signals.\n"); } break; - case 'A': - sscanf (optarg, "%i", &opts.mod_threshold); - fprintf (stderr,"Setting C4FM/QPSK auto detection threshold to %i\n", opts.mod_threshold); - break; //this was missing a break - - //Disabled and switches reassigned to M17 User Data Argumeents - // case 'S': //disabled, using for M17 encoder user SMS message - // sscanf (optarg, "%i", &opts.ssize); - // if (opts.ssize > 128) - // { - // opts.ssize = 128; - // } - // else if (opts.ssize < 1) - // { - // opts.ssize = 1; - // } - // fprintf (stderr,"Setting QPSK symbol buffer to %i\n", opts.ssize); - // break; - // case 'M': //disabled, using for M17 user data - // sscanf (optarg, "%i", &opts.msize); - // if (opts.msize > 1024) - // { - // opts.msize = 1024; - // } - // else if (opts.msize < 1) - // { - // opts.msize = 1; - // } - // fprintf (stderr,"Setting QPSK Min/Max buffer to %i\n", opts.msize); - // break; case 'r': opts.playfiles = 1;