diff --git a/examples/example_aes_keys.csv b/examples/example_aes_keys.csv new file mode 100644 index 0000000..66067e4 --- /dev/null +++ b/examples/example_aes_keys.csv @@ -0,0 +1,7 @@ +keyid(hex), keyvalue(hex) +0001,0000000000000000,0000000000000000,0000000000000000,0000002823d87923 +0003,0101010101010101,0101010101010101 +0004,0101010101010101,0101010101010101,0101010101010101,0101010101010101 +C197,A753BC945DE5E0F1,EC1970F8565154E6,D9DF2FAC6278FA93,B531D2CC046E93A2 +0067,0000000000000000,0000000000000000,0000000000000000,DEADBEEFBAADF00D +0000,0000000000000000,0000000000000000,0000000000000000,0000000000000001 \ No newline at end of file diff --git a/include/dsd.h b/include/dsd.h index f79f4b7..529c32f 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -596,6 +596,16 @@ typedef struct unsigned long long int K4; int M; int menuopen; + + //AES Key Segments + unsigned long long int A1[2]; + unsigned long long int A2[2]; + unsigned long long int A3[3]; + unsigned long long int A4[4]; + int aes_key_loaded[2]; + + //xl specific, we need to know if the ESS is from HDU, or from LDU2 + int xl_is_hdu; unsigned int debug_audio_errors; unsigned int debug_audio_errorsR; @@ -718,6 +728,23 @@ typedef struct int DMRvcL; int DMRvcR; + //keystream octet and bit arrays + uint8_t ks_octetL[129*18]; //arbitary size, but large enough for the largest packed PDUs + uint8_t ks_octetR[129*18]; //arbitary size, but large enough for the largest packed PDUs + uint8_t ks_bitstreamL[128*18*8]; //arbitary size, but large enough for the largest PDUs + uint8_t ks_bitstreamR[129*18*8]; //arbitary size, but large enough for the largest PDUs + int octet_counter; + long int bit_counterL; + long int bit_counterR; + + //AES Specific Variables + uint8_t aes_key[32]; //was 64 for some reason + uint8_t aes_iv[16]; + uint8_t aes_ivR[16]; + + //NXDN DES and AES, signal new VCALL_IV and new IV + uint8_t nxdn_new_iv; //1 when a new IV comes in, else 0 + short int dmr_encL; short int dmr_encR; @@ -828,7 +855,7 @@ typedef struct uint8_t nxdn_bw; //multi-key array - unsigned long long int rkey_array[0xFFFF]; + unsigned long long int rkey_array[0x1FFFF]; int keyloader; //let us know the keyloader is active //dmr late entry mi @@ -1477,9 +1504,25 @@ 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_voice_decrypt (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); +//DES function prototypes +void des_multi_keystream_output (unsigned long long int mi, unsigned long long int key_ulli, uint8_t * output, int type, int len); +void tdea_multi_keystream_output (unsigned long long int mi, uint8_t * key, uint8_t * output, int type, int len); + +//AES function prototypes +void aes_ofb_keystream_output (uint8_t * iv, uint8_t * key, uint8_t * output, int type, int nblocks); +void aes_ecb_bytewise_payload_crypt (uint8_t * input, uint8_t * key, uint8_t * output, int type, int de); +void aes_cbc_bytewise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * in, uint8_t * out, int type, int nblocks, int de); +void aes_cfb_bytewise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * in, uint8_t * out, int type, int nblocks, int de); +void aes_ctr_bytewise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * payload, int type); +void aes_ctr_bitwise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * payload, int type); + +//LFSR to expand either a DMR 32-bit or P25 64-bit MI into a 128-bit IV for AES +void LFSR128(dsd_state * state); +void LFSR128d(dsd_state * state); + #ifdef __cplusplus extern "C" { diff --git a/src/2.c b/src/2.c deleted file mode 100644 index 6275863..0000000 --- a/src/2.c +++ /dev/null @@ -1,7 +0,0 @@ -/*------------------------------------------------------------------------------- - * 2.c - * Placeholder File 2 -- This file is for temporary code storage - * - * - * - *-----------------------------------------------------------------------------*/ \ No newline at end of file diff --git a/src/4.c b/src/4.c deleted file mode 100644 index 801a052..0000000 --- a/src/4.c +++ /dev/null @@ -1,7 +0,0 @@ -/*------------------------------------------------------------------------------- - * 4.c - * Placeholder File 4 -- This file is for temporary code storage - * - * - * - *-----------------------------------------------------------------------------*/ \ No newline at end of file diff --git a/src/5.c b/src/5.c deleted file mode 100644 index f05bb01..0000000 --- a/src/5.c +++ /dev/null @@ -1,7 +0,0 @@ -/*------------------------------------------------------------------------------- - * 5.c - * Placeholder File 5 -- This file is for temporary code storage - * - * - * - *-----------------------------------------------------------------------------*/ \ No newline at end of file diff --git a/src/crypt-aes.c b/src/crypt-aes.c new file mode 100644 index 0000000..99e03d7 --- /dev/null +++ b/src/crypt-aes.c @@ -0,0 +1,921 @@ +/*------------------------------------------------------------------------------- + * aes.c Tinier AES + * Easy To Use (and configurable) AES Output and Utility Bit/Byte Functions + * + * Modified Tiny AES code for more variable nk/nr/nb values, all in one file + * https://github.com/kokke/tiny-AES-c + *-----------------------------------------------------------------------------*/ + + +/* + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + For more information, please refer to + +*/ + +#include +#include +#include +// #include "aes.h" + +#define AES_BLOCKLEN 16 +unsigned Nb = 4; +unsigned Nk = 8; +unsigned Nr = 14; + +struct AES_ctx +{ + uint8_t RoundKey[240]; + uint8_t Iv[16]; +}; + +//internal function prototypes +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); +void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); +void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); +void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); + +typedef uint8_t state_t[4][4]; + +static const uint8_t sbox[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; + +static const uint8_t rsbox[256] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; + +static const uint8_t Rcon[11] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; + +#define getSBoxValue(num) (sbox[(num)]) + +static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) +{ + unsigned i, j, k; + uint8_t tempa[4]; // Used for the column/row operations + + // The first round key is the key itself. + for (i = 0; i < Nk; ++i) + { + RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; + RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; + RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; + RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + } + + // All other round keys are found from the previous round keys. + for (i = Nk; i < Nb * (Nr + 1); ++i) + { + { + k = (i - 1) * 4; + tempa[0]=RoundKey[k + 0]; + tempa[1]=RoundKey[k + 1]; + tempa[2]=RoundKey[k + 2]; + tempa[3]=RoundKey[k + 3]; + + } + + if (i % Nk == 0) + { + // This function shifts the 4 bytes in a word to the left once. + // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] + + // Function RotWord() + { + const uint8_t u8tmp = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = u8tmp; + } + + // SubWord() is a function that takes a four-byte input word and + // applies the S-box to each of the four bytes to produce an output word. + + // Function Subword() + { + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + } + + tempa[0] = tempa[0] ^ Rcon[i/Nk]; + } + + if (Nk == 8) //only run if using AES256 (Nk == 8) + { + if (i % Nk == 4) + { + // Function Subword() + { + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + } + } + } + + j = i * 4; k=(i - Nk) * 4; + RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; + RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; + RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; + RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; + } +} + +//input bit array, return output as up to a 64-bit value +uint64_t convert_bits_into_output_ta(uint8_t * input, int len) +{ + int i; + uint64_t output = 0; + for(i = 0; i < len; i++) + { + output <<= 1; + output |= (uint64_t)(input[i] & 1); + } + return output; +} + +//take x amount of bits and pack into len amount of bytes (symmetrical) +void pack_bit_array_into_byte_array_ta (uint8_t * input, uint8_t * output, int len) +{ + int i; + for (i = 0; i < len; i++) + output[i] = (uint8_t)convert_bits_into_output_ta(&input[i*8], 8); +} + +//take len amount of bytes and unpack back into a bit array +void unpack_byte_array_into_bit_array_ta (uint8_t * input, uint8_t * output, int len) +{ + int i = 0, k = 0; + for (i = 0; i < len; i++) + { + output[k++] = (input[i] >> 7) & 1; + output[k++] = (input[i] >> 6) & 1; + output[k++] = (input[i] >> 5) & 1; + output[k++] = (input[i] >> 4) & 1; + output[k++] = (input[i] >> 3) & 1; + output[k++] = (input[i] >> 2) & 1; + output[k++] = (input[i] >> 1) & 1; + output[k++] = (input[i] >> 0) & 1; + } +} + +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) +{ + KeyExpansion(ctx->RoundKey, key); +} +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) +{ + KeyExpansion(ctx->RoundKey, key); + memcpy (ctx->Iv, iv, AES_BLOCKLEN); +} +void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv) +{ + memcpy (ctx->Iv, iv, AES_BLOCKLEN); +} + +static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) +{ + uint8_t i,j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; + } + } +} + +static void SubBytes(state_t* state) +{ + uint8_t i, j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + (*state)[j][i] = getSBoxValue((*state)[j][i]); + } + } +} + +static void ShiftRows(state_t* state) +{ + uint8_t temp; + + // Rotate first row 1 columns to left + temp = (*state)[0][1]; + (*state)[0][1] = (*state)[1][1]; + (*state)[1][1] = (*state)[2][1]; + (*state)[2][1] = (*state)[3][1]; + (*state)[3][1] = temp; + + // Rotate second row 2 columns to left + temp = (*state)[0][2]; + (*state)[0][2] = (*state)[2][2]; + (*state)[2][2] = temp; + + temp = (*state)[1][2]; + (*state)[1][2] = (*state)[3][2]; + (*state)[3][2] = temp; + + // Rotate third row 3 columns to left + temp = (*state)[0][3]; + (*state)[0][3] = (*state)[3][3]; + (*state)[3][3] = (*state)[2][3]; + (*state)[2][3] = (*state)[1][3]; + (*state)[1][3] = temp; +} + +static uint8_t xtime(uint8_t x) +{ + return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); +} + +static void MixColumns(state_t* state) +{ + uint8_t i; + uint8_t Tmp, Tm, t; + for (i = 0; i < 4; ++i) + { + t = (*state)[i][0]; + Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; + Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; + Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; + Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; + Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; + } +} + +#define Multiply(x, y) \ + ( ((y & 1) * x) ^ \ + ((y>>1 & 1) * xtime(x)) ^ \ + ((y>>2 & 1) * xtime(xtime(x))) ^ \ + ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ + ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ + + +#define getSBoxInvert(num) (rsbox[(num)]) + +static void InvMixColumns(state_t* state) +{ + int i; + uint8_t a, b, c, d; + for (i = 0; i < 4; ++i) + { + a = (*state)[i][0]; + b = (*state)[i][1]; + c = (*state)[i][2]; + d = (*state)[i][3]; + + (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); + (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); + (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); + (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); + } +} + +static void InvSubBytes(state_t* state) +{ + uint8_t i, j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + (*state)[j][i] = getSBoxInvert((*state)[j][i]); + } + } +} + +static void InvShiftRows(state_t* state) +{ + uint8_t temp; + + // Rotate first row 1 columns to right + temp = (*state)[3][1]; + (*state)[3][1] = (*state)[2][1]; + (*state)[2][1] = (*state)[1][1]; + (*state)[1][1] = (*state)[0][1]; + (*state)[0][1] = temp; + + // Rotate second row 2 columns to right + temp = (*state)[0][2]; + (*state)[0][2] = (*state)[2][2]; + (*state)[2][2] = temp; + + temp = (*state)[1][2]; + (*state)[1][2] = (*state)[3][2]; + (*state)[3][2] = temp; + + // Rotate third row 3 columns to right + temp = (*state)[0][3]; + (*state)[0][3] = (*state)[1][3]; + (*state)[1][3] = (*state)[2][3]; + (*state)[2][3] = (*state)[3][3]; + (*state)[3][3] = temp; +} + +// Cipher is the main function that encrypts the PlainText, +// or produces a keystream, depending on application. +static void Cipher(state_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + // Add the First round key to the state before starting the rounds. + AddRoundKey(0, state, RoundKey); + + // There will be Nr rounds. + // The first Nr-1 rounds are identical. + // These Nr rounds are executed in the loop below. + // Last one without MixColumns() + for (round = 1; ; ++round) + { + SubBytes(state); + ShiftRows(state); + if (round == Nr) { + break; + } + MixColumns(state); + AddRoundKey(round, state, RoundKey); + } + // Add round key to last round + AddRoundKey(Nr, state, RoundKey); +} + +static void InvCipher(state_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + // Add the First round key to the state before starting the rounds. + AddRoundKey(Nr, state, RoundKey); + + // There will be Nr rounds. + // The first Nr-1 rounds are identical. + // These Nr rounds are executed in the loop below. + // Last one without InvMixColumn() + for (round = (Nr - 1); ; --round) + { + InvShiftRows(state); + InvSubBytes(state); + AddRoundKey(round, state, RoundKey); + if (round == 0) { + break; + } + InvMixColumns(state); + } + +} + +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) +{ + // The next function call encrypts the PlainText with the Key using AES algorithm. + Cipher((state_t*)buf, ctx->RoundKey); +} + +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) +{ + // The next function call decrypts the PlainText with the Key using AES algorithm. + InvCipher((state_t*)buf, ctx->RoundKey); +} + +static void XorWithIv(uint8_t* buf, const uint8_t* Iv) +{ + uint8_t i; + for (i = 0; i < AES_BLOCKLEN; ++i) + { + buf[i] ^= Iv[i]; + } +} + +void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, size_t length) +{ + size_t i; + uint8_t *Iv = ctx->Iv; + for (i = 0; i < length; i += AES_BLOCKLEN) + { + XorWithIv(buf, Iv); + Cipher((state_t*)buf, ctx->RoundKey); + Iv = buf; + buf += AES_BLOCKLEN; + } + /* store Iv in ctx for next call */ + memcpy(ctx->Iv, Iv, AES_BLOCKLEN); +} + +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) +{ + size_t i; + uint8_t storeNextIv[AES_BLOCKLEN]; + for (i = 0; i < length; i += AES_BLOCKLEN) + { + memcpy(storeNextIv, buf, AES_BLOCKLEN); + InvCipher((state_t*)buf, ctx->RoundKey); + XorWithIv(buf, ctx->Iv); + memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); + buf += AES_BLOCKLEN; + } + +} + +/* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */ +void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) +{ + uint8_t buffer[AES_BLOCKLEN]; + + size_t i; + int bi; + for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) + { + if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */ + { + + memcpy(buffer, ctx->Iv, AES_BLOCKLEN); + Cipher((state_t*)buffer,ctx->RoundKey); + + /* Increment Iv and handle overflow */ + for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) + { + /* inc will overflow */ + if (ctx->Iv[bi] == 255) + { + ctx->Iv[bi] = 0; + continue; + } + ctx->Iv[bi] += 1; + break; + } + bi = 0; + } + + buf[i] = (buf[i] ^ buffer[bi]); + } + +} + +//byte-wise output of AES OFB Keystream +//input iv is a 16-byte uint8_t array of initialization vector +//input key is up to 32-byte uint8_t array of key value +//input type is the type/key len of AES required (0-128, 1-192, 2-256) +//input nblocks is the number of rounds of 16-byte keystream output blocks requried +//output is a uint8_t bytewise array, each round filled with 16-bytes from aes keystream output +void aes_ofb_keystream_output (uint8_t * iv, uint8_t * key, uint8_t * output, int type, int nblocks) +{ + + int i; + uint8_t input_register[16]; //OFB Input Register + memset (input_register, 0, sizeof(input_register)); + + //Set values specific to type (128/192/256) + if (type == 0) //128 + { + Nb = 4; + Nk = 4; + Nr = 10; + } + else if (type == 1) //192 + { + Nb = 4; + Nk = 6; + Nr = 12; + } + else //if (type == 2) //256 + { + Nb = 4; + Nk = 8; + Nr = 14; + } + + struct AES_ctx ctx; + + //load first round of input_register with received IV (OFB First Input Register) + memcpy (input_register, iv, 16*sizeof(uint8_t) ); + + //initialize the key variable for the Cipher function + memset (ctx.RoundKey, 0, 240*sizeof(uint8_t)); + KeyExpansion(ctx.RoundKey, key); + + //execute the cipher function, and copy ciphered input_register to output for required number of rounds + for (i = 0; i < nblocks; i++) + { + Cipher((state_t*)input_register, ctx.RoundKey); //input_register is returned as output, and is put back in as object feedback + memcpy (output+(i*16), input_register, 16*sizeof(uint8_t) ); //copy ciphered input_register to output + } + +} + +//byte-wise AES CFB (Cipher Feedback) Payload operating in 128-bit block mode +//input in is a uint8_t bytewise array,is the input to be ciphered (encrypted or decrypted) +//input iv is a 16-byte uint8_t array of initialization vector +//input key is up to 32-byte uint8_t array of key value +//input type is the type/key len of AES required (0-128, 1-192, 2-256) +//input nblocks is the number of rounds of 16-byte payload blocks requried (last block will need padding if not flush) +//output out is a uint8_t bytewise array, each round filled with 16-bytes of cfb ciphered output (encrypted or decrypted) +//de is a bit-flag signalling to run Cipher (encrypt) on 1, or InvCipher (decrypt) on 0 +void aes_cfb_bytewise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * in, uint8_t * out, int type, int nblocks, int de) +{ + + int i, j; + uint8_t input_register[16]; //Input Register + memset (input_register, 0, sizeof(input_register)); + + //Set values specific to type (128/192/256) + if (type == 0) //128 + { + Nb = 4; + Nk = 4; + Nr = 10; + } + else if (type == 1) //192 + { + Nb = 4; + Nk = 6; + Nr = 12; + } + else //if (type == 2) //256 + { + Nb = 4; + Nk = 8; + Nr = 14; + } + + struct AES_ctx ctx; + + //load first round of input_register with received IV (CFB First Input Register) + memcpy (input_register, iv, 16*sizeof(uint8_t) ); + + //initialize the key variable for the Cipher function + memset (ctx.RoundKey, 0, 240*sizeof(uint8_t)); + KeyExpansion(ctx.RoundKey, key); + + //execute the cipher function, and copy ciphered input_register to output for required number of rounds + for (i = 0; i < nblocks; i++) + { + + //the cipher is always run in the foward, or encryption mode + Cipher((state_t*)input_register, ctx.RoundKey); + + //xor the current input 'in' to the current state of the input_register for cipher feedback + for (j = 0; j < 16; j++) + input_register[j] ^= in[j+(i*16)]; + + //copy ciphered/xor'd input_register to output 'out' + memcpy (out+(i*16), input_register, 16*sizeof(uint8_t) ); + + //if running in decryption mode, we feed in the next round of input + if (!de) + memcpy(input_register, in+(i*16), 16*sizeof(uint8_t)); + + } + +} + +//byte-wise AES CBC (Cipher Block Chaining) //Yeah, I know this already exists, but wanted a custom convenience wrapper version +//input in is a uint8_t bytewise array,is the input to be ciphered (encrypted or decrypted) +//input iv is a 16-byte uint8_t array of initialization vector +//input key is up to 32-byte uint8_t array of key value +//input type is the type/key len of AES required (0-128, 1-192, 2-256) +//input nblocks is the number of rounds of 16-byte payload blocks requried (last block will need padding if not flush) +//output out is a uint8_t bytewise array, each round filled with 16-bytes of cfb ciphered output (encrypted or decrypted) +//de is a bit-flag signalling to run Cipher (encrypt) on 1, or InvCipher (decrypt) on 0 +void aes_cbc_bytewise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * in, uint8_t * out, int type, int nblocks, int de) +{ + + int i, j; + uint8_t input_register[16]; //Input Register + memset (input_register, 0, sizeof(input_register)); + + //Set values specific to type (128/192/256) + if (type == 0) //128 + { + Nb = 4; + Nk = 4; + Nr = 10; + } + else if (type == 1) //192 + { + Nb = 4; + Nk = 6; + Nr = 12; + } + else //if (type == 2) //256 + { + Nb = 4; + Nk = 8; + Nr = 14; + } + + struct AES_ctx ctx; + + //load first round of input_register accordingly + if (de) + memcpy (input_register, iv, 16*sizeof(uint8_t) ); + else memcpy (input_register, in, 16*sizeof(uint8_t) ); + + //initialize the key variable for the Cipher function + memset (ctx.RoundKey, 0, 240*sizeof(uint8_t)); + KeyExpansion(ctx.RoundKey, key); + + // + for (i = 0; i < nblocks; i++) + { + + //run encryption or decryption depending on de value + if (de) //encrypt + { + + //xor the current input 'in' pt to the current state of the input_register for cbc feedback + for (j = 0; j < 16; j++) + input_register[j] ^= in[j+(i*16)]; + + Cipher((state_t*)input_register, ctx.RoundKey); + + //copy ciphered input_register to output 'out' + memcpy (out+(i*16), input_register, 16*sizeof(uint8_t) ); + + } + + else //decrypt + { + + InvCipher((state_t*)input_register, ctx.RoundKey); + + //copy ciphered input_register to output 'out' + memcpy (out+(i*16), input_register, 16*sizeof(uint8_t) ); + + //xor the current output by IV, or by last received CT + if (i == 0) + { + for (j = 0; j < 16; j++) + out[j] ^= iv[j]; + } + else + { + for (j = 0; j < 16; j++) + out[j+(i*16)] ^= in[j+((i-1)*16)]; + } + + //copy in next segment for input_register (if not last) + if (i < nblocks) + memcpy(input_register, in+((i+1)*16), 16*sizeof(uint8_t) ); + + } + + } + +} + +//byte-wise AES CBC_MAC (Cipher Block Chaining Message Authentication) //This is slightly different than above, no IV is present, +//but if iv is desireable, it will need to be pre-XOR'd with the first plaintext input block by the calling function +//input in is a uint8_t bytewise array, is the input to be ciphered. +//input key is up to 32-byte uint8_t array of key value +//input type is the type/key len of AES required (0-128, 1-192, 2-256) +//input nblocks is the number of rounds of 16-byte payload blocks requried (last block will need padding if not flush) +//output out is a uint8_t bytewise array, with only the final round output as the MAC octets +//NOTE: When doing a cbc_mac, you should only run it in the forward (encryption) mode to get the mac bytes +void aes_cbc_mac_generator (uint8_t * key, uint8_t * in, uint8_t * out, int type, int nblocks) +{ + + int i, j; + uint8_t input_register[16]; //Input Register + memset (input_register, 0, sizeof(input_register)); + + //Set values specific to type (128/192/256) + if (type == 0) //128 + { + Nb = 4; + Nk = 4; + Nr = 10; + } + else if (type == 1) //192 + { + Nb = 4; + Nk = 6; + Nr = 12; + } + else //if (type == 2) //256 + { + Nb = 4; + Nk = 8; + Nr = 14; + } + + struct AES_ctx ctx; + + //initialize the key variable for the Cipher function + memset (ctx.RoundKey, 0, 240*sizeof(uint8_t)); + KeyExpansion(ctx.RoundKey, key); + + // + for (i = 0; i < nblocks; i++) + { + + //xor the current input 'in' pt to the current state of the input_register for cbc feedback + //if this is the first iteration, this will load the first round plain text instead + for (j = 0; j < 16; j++) + input_register[j] ^= in[j+((i+0)*16)]; + + Cipher((state_t*)input_register, ctx.RoundKey); + + //debug, load out all intermediate output register values + // memcpy (out+(i*16), input_register, 16*sizeof(uint8_t) ); + + } + + //copy final ciphered input_register to output 'out', user will determine how many bytes of output they want for MAC + memcpy (out, input_register, 16*sizeof(uint8_t) ); + +} + +//byte-wise output of AES ECB Ciphering/Deciphering +//input is uint8_t byte-wise (16-bytes) data to be ciphered or deciphered +//input key is up to 32-byte uint8_t array of key value +//input type is the type/len of AES required (0-128, 1-192, 2-256) +//output is a uint8_t bytewise array of ciphered or deciphered input +//de is a bit-flag signalling to run Cipher (encrypt) on 1, or InvCipher (decrypt) on 0 +void aes_ecb_bytewise_payload_crypt (uint8_t * input, uint8_t * key, uint8_t * output, int type, int de) +{ + + uint8_t input_register[16]; //ECB Input Register + memset (input_register, 0, sizeof(input_register)); + + //Set values specific to type (128/192/256) + if (type == 0) //128 + { + Nb = 4; + Nk = 4; + Nr = 10; + } + else if (type == 1) //192 + { + Nb = 4; + Nk = 6; + Nr = 12; + } + else //if (type == 2) //256 + { + Nb = 4; + Nk = 8; + Nr = 14; + } + + struct AES_ctx ctx; + + //load input_register with received input (ECB Payload) + memcpy (input_register, input, 16*sizeof(uint8_t) ); + + //initialize the key variable for the Cipher function + memset (ctx.RoundKey, 0, 240*sizeof(uint8_t)); + KeyExpansion(ctx.RoundKey, key); + + //run encryption or decryption depending on de value + if (de) //encrypt + Cipher((state_t*)input_register, ctx.RoundKey); + else //decrypt + InvCipher((state_t*)input_register, ctx.RoundKey); + + //copy ciphered/deciphered input_register to output + memcpy (output, input_register, 16*sizeof(uint8_t) ); + +} + +//symmetrical ctr mode payload encryption and decryption +void aes_ctr_bitwise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * payload, int type) +{ + + //Set values specific to type (128/192/256) + if (type == 0) //128 + { + Nb = 4; + Nk = 4; + Nr = 10; + } + else if (type == 1) //192 + { + Nb = 4; + Nk = 6; + Nr = 12; + } + else //if (type == 2) //256 + { + Nb = 4; + Nk = 8; + Nr = 14; + } + + struct AES_ctx ctx; + + //init and set the iv and key variables + memset (ctx.RoundKey, 0, 240*sizeof(uint8_t)); + memset (ctx.Iv, 0, 16*sizeof(uint8_t)); + + KeyExpansion(ctx.RoundKey, key); + memcpy (ctx.Iv, iv, AES_BLOCKLEN); + + //pack input bit-wise payload to byte array + uint8_t payload_bytes[16]; + memset (payload_bytes, 0, sizeof(payload_bytes)); + pack_bit_array_into_byte_array_ta (payload, payload_bytes, 16); + + //pass to internal CTR handler for payload + AES_CTR_xcrypt_buffer(&ctx, payload_bytes, 16); + + //unpack output bytes back to bits + unpack_byte_array_into_bit_array_ta(payload_bytes, payload, 16); + +} + +//symmetrical ctr mode payload encryption and decryption +void aes_ctr_bytewise_payload_crypt (uint8_t * iv, uint8_t * key, uint8_t * payload, int type) +{ + + //Set values specific to type (128/192/256) + if (type == 0) //128 + { + Nb = 4; + Nk = 4; + Nr = 10; + } + else if (type == 1) //192 + { + Nb = 4; + Nk = 6; + Nr = 12; + } + else //if (type == 2) //256 + { + Nb = 4; + Nk = 8; + Nr = 14; + } + + struct AES_ctx ctx; + + //init and set the iv and key variables + memset (ctx.RoundKey, 0, 240*sizeof(uint8_t)); + memset (ctx.Iv, 0, 16*sizeof(uint8_t)); + + KeyExpansion(ctx.RoundKey, key); + memcpy (ctx.Iv, iv, AES_BLOCKLEN); + + //pass to internal CTR handler for payload + AES_CTR_xcrypt_buffer(&ctx, payload, 16); + +} diff --git a/src/crypt-des.c b/src/crypt-des.c new file mode 100644 index 0000000..44afae3 --- /dev/null +++ b/src/crypt-des.c @@ -0,0 +1,831 @@ +/*------------------------------------------------------------------------------- + * des.c Crypthings + * DES Alg + *-----------------------------------------------------------------------------*/ + +#include +#include +#include + +#include +#include + +//NOTE: The SLUT boxes are S boxes with additional calculations so we don't have +//to manually sort out row and column values and can cut down on operations + +uint8_t SLUT1[64] = { +0xE0,0x00,0x40,0xF0,0xD0,0x70,0x10,0x40, +0x20,0xE0,0xF0,0x20,0xB0,0xD0,0x80,0x10, +0x30,0xA0,0xA0,0x60,0x60,0xC0,0xC0,0xB0, +0x50,0x90,0x90,0x50,0x00,0x30,0x70,0x80, +0x40,0xF0,0x10,0xC0,0xE0,0x80,0x80,0x20, +0xD0,0x40,0x60,0x90,0x20,0x10,0xB0,0x70, +0xF0,0x50,0xC0,0xB0,0x90,0x30,0x70,0xE0, +0x30,0xA0,0xA0,0x00,0x50,0x60,0x00,0xD0 +}; + +uint8_t SLUT2[64] = { +0x0F,0x03,0x01,0x0D,0x08,0x04,0x0E,0x07, +0x06,0x0F,0x0B,0x02,0x03,0x08,0x04,0x0E, +0x09,0x0C,0x07,0x00,0x02,0x01,0x0D,0x0A, +0x0C,0x06,0x00,0x09,0x05,0x0B,0x0A,0x05, +0x00,0x0D,0x0E,0x08,0x07,0x0A,0x0B,0x01, +0x0A,0x03,0x04,0x0F,0x0D,0x04,0x01,0x02, +0x05,0x0B,0x08,0x06,0x0C,0x07,0x06,0x0C, +0x09,0x00,0x03,0x05,0x02,0x0E,0x0F,0x09 +}; + +uint8_t SLUT3[64] = { +0xA0,0xD0,0x00,0x70,0x90,0x00,0xE0,0x90, +0x60,0x30,0x30,0x40,0xF0,0x60,0x50,0xA0, +0x10,0x20,0xD0,0x80,0xC0,0x50,0x70,0xE0, +0xB0,0xC0,0x40,0xB0,0x20,0xF0,0x80,0x10, +0xD0,0x10,0x60,0xA0,0x40,0xD0,0x90,0x00, +0x80,0x60,0xF0,0x90,0x30,0x80,0x00,0x70, +0xB0,0x40,0x10,0xF0,0x20,0xE0,0xC0,0x30, +0x50,0xB0,0xA0,0x50,0xE0,0x20,0x70,0xC0 +}; + +uint8_t SLUT4[64] = { +0x07,0x0D,0x0D,0x08,0x0E,0x0B,0x03,0x05, +0x00,0x06,0x06,0x0F,0x09,0x00,0x0A,0x03, +0x01,0x04,0x02,0x07,0x08,0x02,0x05,0x0C, +0x0B,0x01,0x0C,0x0A,0x04,0x0E,0x0F,0x09, +0x0A,0x03,0x06,0x0F,0x09,0x00,0x00,0x06, +0x0C,0x0A,0x0B,0x01,0x07,0x0D,0x0D,0x08, +0x0F,0x09,0x01,0x04,0x03,0x05,0x0E,0x0B, +0x05,0x0C,0x02,0x07,0x08,0x02,0x04,0x0E +}; + +uint8_t SLUT5[64] = { +0x20,0xE0,0xC0,0xB0,0x40,0x20,0x10,0xC0, +0x70,0x40,0xA0,0x70,0xB0,0xD0,0x60,0x10, +0x80,0x50,0x50,0x00,0x30,0xF0,0xF0,0xA0, +0xD0,0x30,0x00,0x90,0xE0,0x80,0x90,0x60, +0x40,0xB0,0x20,0x80,0x10,0xC0,0xB0,0x70, +0xA0,0x10,0xD0,0xE0,0x70,0x20,0x80,0xD0, +0xF0,0x60,0x90,0xF0,0xC0,0x00,0x50,0x90, +0x60,0xA0,0x30,0x40,0x00,0x50,0xE0,0x30 +}; + +uint8_t SLUT6[64] = { +0x0C,0x0A,0x01,0x0F,0x0A,0x04,0x0F,0x02, +0x09,0x07,0x02,0x0C,0x06,0x09,0x08,0x05, +0x00,0x06,0x0D,0x01,0x03,0x0D,0x04,0x0E, +0x0E,0x00,0x07,0x0B,0x05,0x03,0x0B,0x08, +0x09,0x04,0x0E,0x03,0x0F,0x02,0x05,0x0C, +0x02,0x09,0x08,0x05,0x0C,0x0F,0x03,0x0A, +0x07,0x0B,0x00,0x0E,0x04,0x01,0x0A,0x07, +0x01,0x06,0x0D,0x00,0x0B,0x08,0x06,0x0D +}; + +uint8_t SLUT7[64] = { +0x40,0xD0,0xB0,0x00,0x20,0xB0,0xE0,0x70, +0xF0,0x40,0x00,0x90,0x80,0x10,0xD0,0xA0, +0x30,0xE0,0xC0,0x30,0x90,0x50,0x70,0xC0, +0x50,0x20,0xA0,0xF0,0x60,0x80,0x10,0x60, +0x10,0x60,0x40,0xB0,0xB0,0xD0,0xD0,0x80, +0xC0,0x10,0x30,0x40,0x70,0xA0,0xE0,0x70, +0xA0,0x90,0xF0,0x50,0x60,0x00,0x80,0xF0, +0x00,0xE0,0x50,0x20,0x90,0x30,0x20,0xC0 +}; + +uint8_t SLUT8[64] = { +0x0D,0x01,0x02,0x0F,0x08,0x0D,0x04,0x08, +0x06,0x0A,0x0F,0x03,0x0B,0x07,0x01,0x04, +0x0A,0x0C,0x09,0x05,0x03,0x06,0x0E,0x0B, +0x05,0x00,0x00,0x0E,0x0C,0x09,0x07,0x02, +0x07,0x02,0x0B,0x01,0x04,0x0E,0x01,0x07, +0x09,0x04,0x0C,0x0A,0x0E,0x08,0x02,0x0D, +0x00,0x0F,0x06,0x0C,0x0A,0x09,0x0D,0x00, +0x0F,0x03,0x03,0x05,0x05,0x06,0x08,0x0B +}; + +//initial permutation IP (on input) +uint8_t initial_register_permutation[64] = { +58, 50, 42, 34, 26, 18, 10, 2, +60, 52, 44, 36, 28, 20, 12, 4, +62, 54, 46, 38, 30, 22, 14, 6, +64, 56, 48, 40, 32, 24, 16, 8, +57, 49, 41, 33, 25, 17, 9, 1, +59, 51, 43, 35, 27, 19, 11, 3, +61, 53, 45, 37, 29, 21, 13, 5, +63, 55, 47, 39, 31, 23, 15, 7}; + +//D-Box Expansion (sometimes noted as E BIT-SELECTION TABLE) +uint8_t message_expansion[48] = { +32, 1, 2, 3, 4, 5, +4, 5, 6, 7, 8, 9, +8, 9, 10, 11, 12, 13, +12, 13, 14, 15, 16, 17, +16, 17, 18, 19, 20, 21, +20, 21, 22, 23, 24, 25, +24, 25, 26, 27, 28, 29, +28, 29, 30, 31, 32, 1}; + +// (sometimes noted as simply 'P') +uint8_t right_half_permutation[32] = { +16, 7, 20, 21, +29, 12, 28, 17, +1, 15, 23, 26, +5, 18, 31, 10, +2, 8, 24, 14, +32, 27, 3, 9, +19, 13, 30, 6, +22, 11, 4, 25}; + +//inverse initial PI, a.k.a. final permutation (on output) +uint8_t final_register_permutation[64] = { +40, 8, 48, 16, 56, 24, 64, 32, +39, 7, 47, 15, 55, 23, 63, 31, +38, 6, 46, 14, 54, 22, 62, 30, +37, 5, 45, 13, 53, 21, 61, 29, +36, 4, 44, 12, 52, 20, 60, 28, +35, 3, 43, 11, 51, 19, 59, 27, +34, 2, 42, 10, 50, 18, 58, 26, +33, 1, 41, 9, 49, 17, 57, 25}; + +//initial key permutation +uint8_t pc1_key_permutation[56] = { +57, 49, 41, 33, 25, 17, 9, +1, 58, 50, 42, 34, 26, 18, +10, 2, 59, 51, 43, 35, 27, +19, 11, 3, 60, 52, 44, 36, +63, 55, 47, 39, 31, 23, 15, +7, 62, 54, 46, 38, 30, 22, +14, 6, 61, 53, 45, 37, 29, +21, 13, 5, 28, 20, 12, 4}; + +//sub c and d key permutation +uint8_t pc2_key_permutation[48] = { +//c bits +14,17,11,24,1,5, +3,28,15,6,21,10, +23,19,12,4,26,8, +16,7,27,20,13,2, +//d bits (with -28 offset to simply/only have one permute function) +13,24,3,9,19,27, +2,12,23,17,5,20, +16,21,11,28,6,25, +18,14,22,8,1,4 +}; + +uint8_t key_shift_sizes[17] = { +1, +1, 1, 2, 2, +2, 2, 2, 2, +1, 2, 2, 2, +2, 2, 2, 1}; + +uint8_t key_shift_bytes[17] = { +0x80, +0x80, 0x80, 0xC0, 0xC0, +0xC0, 0xC0, 0xC0, 0xC0, +0x80, 0xC0, 0xC0, 0xC0, +0xC0, 0xC0, 0xC0, 0x80}; + +uint8_t key_shift_x[4] = {8,8,8,4}; + +uint8_t key_shift_y[4] = {1,2,3,0}; + +//input is byte-wise array, output is byte-wise array +void permute(uint8_t * input, uint8_t * output, uint8_t * table, uint8_t start, uint8_t end) +{ + + for (uint8_t i = start; i < end; i++) + { + uint8_t tdiv = (table[i] - 1) / 8; + uint8_t tmod = (table[i] - 1) % 8; + uint8_t idiv = i/8; + uint8_t imod = i%8; + + //need a way to simplify or get rid of all these shifts + uint8_t bit = (((input[tdiv] & (0x80 >> tmod)) << tmod) >> imod); + output[idiv] |= bit; + } + +} + +void rotate_sub_keys(uint8_t * Kc, uint8_t * Kd, uint8_t shift_size, uint8_t shift_byte) +{ + + uint8_t sb1[4]; memset(sb1, 0, sizeof(sb1)); + uint8_t sb2[4]; memset(sb2, 0, sizeof(sb2)); + + for (uint8_t i = 0; i < 4; i++) + { + sb1[i] = shift_byte & Kc[i]; + sb2[i] = shift_byte & Kd[i]; + } + + for (uint8_t i = 0; i < 4; i++) + { + + uint8_t x = key_shift_x[i]; + uint8_t y = key_shift_y[i]; + + Kc[i] <<= shift_size; + Kd[i] <<= shift_size; + + Kc[i] |= (sb1[y] >> (x - shift_size)); + Kd[i] |= (sb2[y] >> (x - shift_size)); + + } +} + +void des_cipher (uint8_t * main_key, uint8_t * input_register, uint8_t * output_register, uint8_t de) +{ + + //starting and ending permutations + uint8_t initial_permutation[8]; memset(initial_permutation, 0, sizeof(initial_permutation)); + uint8_t pre_end_permutation[8]; memset(pre_end_permutation, 0, sizeof(pre_end_permutation)); + + //intermediate left, right, and expansion/selection arrays + uint8_t left[4]; memset(left, 0, sizeof(left)); + uint8_t right[4]; memset(right, 0, sizeof(right)); + uint8_t rperm[4]; memset(rperm, 0, sizeof(rperm)); + uint8_t exp[6]; memset(exp, 0, sizeof(exp)); + uint8_t sel[4]; memset(sel, 0, sizeof(sel)); + + //key sets + uint8_t Ks[16][7]; memset(Ks, 0, sizeof(Ks)); + uint8_t Kc[4]; memset(Kc, 0, sizeof(Kc)); + uint8_t Kd[4]; memset(Kd, 0, sizeof(Kd)); + + //initial Ks permutation and shuffle to Kc and Kd + permute (main_key, Ks[0], pc1_key_permutation, 0, 56); + for (uint8_t i = 0; i < 3; i++) + { + Kc[i] = Ks[0][i]; + } + Kc[3] = Ks[0][3] & 0xF0; + for (uint8_t i = 0; i < 3; i++) + { + Kd[i] = (Ks[0][i+3] & 0x0F) << 4; + Kd[i] |= (Ks[0][i+4] & 0xF0) >> 4; + } + Kd[3] = (Ks[0][6] & 0x0F) << 4; + + //reset Ks + memset(Ks, 0, sizeof(Ks)); + + //create the 16 Ks rounds + for (uint8_t i = 0; i < 16; i++) + { + uint8_t shift_size = key_shift_sizes[i+1]; + uint8_t shift_byte = key_shift_bytes[i+1]; + rotate_sub_keys(Kc, Kd, shift_size, shift_byte); + permute (Kc, Ks[i], pc2_key_permutation, 0, 24); + permute (Kd, Ks[i], pc2_key_permutation, 24, 48); + } + + //permute the input_register with the ip (initial_register_permutation) table + permute (input_register, initial_permutation, initial_register_permutation, 0, 64); + + //copy the initial permutation to left and right half arrays + memcpy (left, initial_permutation+0, sizeof(left)); + memcpy (right, initial_permutation+4, sizeof(right)); + + //16 fiestel rounds + for (uint8_t f = 0; f < 16; f++) + { + + //reset rperm and exp arrays + memset(rperm, 0, sizeof(rperm)); + memset(exp, 0, sizeof(exp)); + + //expand right half from 32-bit to 48-bit + permute (right, exp, message_expansion, 0, 48); + + //apply current iteration keyset to the expanded array (encryption cycles Ks forward, decryption goes in reverse) + if (de == 1) + { + for (uint8_t i = 0; i < 6; i++) + exp[i] ^= Ks[f][i]; + } + else + { + for (uint8_t i = 0; i < 6; i++) + exp[i] ^= Ks[15-f][i]; + } + + //extract 6 bits for each sbox swap from the expanded array + uint8_t e1 = exp[0] >> 2; + uint8_t e2 = ((exp[0] & 0x3) << 4) | (exp[1] >> 4); + uint8_t e3 = ((exp[1] & 0xF) << 2) | (exp[2] >> 6); + uint8_t e4 = exp[2] & 0x3F; + + uint8_t e5 = exp[3] >> 2; + uint8_t e6 = ((exp[3] & 0x3) << 4) | (exp[4] >> 4); + uint8_t e7 = ((exp[4] & 0xF) << 2) | (exp[5] >> 6); + uint8_t e8 = exp[5] & 0x3F; + + //select 32-bits of each 48-bit expansion via modified S Box Look Up Tables + //swap the 6 bits for 4 bits via SLUT tables and OR them together into a selection array + sel[0] = SLUT1[e1] | SLUT2[e2]; + sel[1] = SLUT3[e3] | SLUT4[e4]; + sel[2] = SLUT5[e5] | SLUT6[e6]; + sel[3] = SLUT7[e7] | SLUT8[e8]; + + //permute the selected 32-bits into a new right half + permute (sel, rperm, right_half_permutation, 0, 32); + + //xor new right half against left half + for (uint8_t i = 0; i < 4; i++) + rperm[i] ^= left[i]; + + //swap old right half to left, set new right half to rperm + memcpy (left, right, sizeof(left)); + memcpy (right, rperm, sizeof(right)); + + } //end fiestel rounds f + + //combine right and left into the pre_end_permutation array + memcpy (pre_end_permutation+0, right, sizeof(right)); + memcpy (pre_end_permutation+4, left, sizeof(left)); + + //carry out the final permuation to get the completed output_register for this cipher iteration + permute (pre_end_permutation, output_register, final_register_permutation, 0, 64); + +} + +void des56_ofb_keystream_output (uint8_t * main_key, uint8_t * iv, uint8_t * ks_bytes, uint8_t de, int16_t nblocks) +{ + + //cipher input and output + uint8_t input_register[8]; memset(input_register, 0, sizeof(input_register)); + uint8_t output_register[8]; memset(output_register, 0, sizeof(output_register)); + + //copy the IV to the input_register (make copy so we don't manipulate the calling functions copy) + memcpy(input_register, iv, sizeof(input_register)); + + //execute the des_cipher in output feedback mode + for (int16_t i = 0; i < nblocks; i++) + { + //de should be 1 here for encryption mode + des_cipher(main_key, input_register, output_register, de); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input register + memcpy(ks_bytes+(i*8), output_register, sizeof(output_register)); //copy output_register to ks_bytes + iteration offset of times 8 + memset(output_register, 0, sizeof(output_register)); //reset output register + } + +} + +//the des_cipher function is already ECB mode, this convenience wrapper is just available as a reminder to illustrate that point +void des56_ecb_payload_crypt (uint8_t * main_key, uint8_t * input_register, uint8_t * output_register, uint8_t de) +{ + //de 1 for encryption mode, 0 for decryption mode + des_cipher(main_key, input_register, output_register, de); +} + +//TDEA, or triple data encryption algorithm, or triple DES, in electronic codebook mode +void tdea_ecb_payload_crypt (uint8_t * K1, uint8_t * K2, uint8_t * K3, uint8_t * input, uint8_t * output, uint8_t de) +{ + + //cipher input and output + uint8_t input_register[8]; memset(input_register, 0, sizeof(input_register)); + uint8_t output_register[8]; memset(output_register, 0, sizeof(output_register)); + + //copy the input to the input_register (make copy so we don't manipulate the calling functions copy) + memcpy(input_register, input, sizeof(input_register)); + + //For TDEA, the cipher alternates between encryption and decryption to the payload + //so, for example, K1 is run as de=1, K2 is run as de=0, and K3 is run as de=1, + //K1 and K3 will always use the same mode and K2 will be the opposite + + //NOTE: If running ECB mode in decryption, make sure to send the keys in reverse order + //so that its K3, K2, and K1 for decryption, and K1, K2, K3 for encryption + + //K1 + des_cipher(K1, input_register, output_register, de); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K2 + de = (de ^ 1) & 1; //flip the de bit + des_cipher(K2, input_register, output_register, de); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K3 + de = (de ^ 1) & 1; //flip the de bit back + des_cipher(K3, input_register, output_register, de); + + //copy payload out + memcpy(output, output_register, sizeof(output_register)); //copy output_register to output + +} + +//TDEA, or triple data encryption algorithm, or triple DES, in cipher block chain mode (64-bit) +//same as usual inputs (byte wise), also, if needing DES56, just feed the same key into K1, K2, and K3 +//if running in decryption mode, this will reverse the key bundle order from (K1, K2, K3) to (K3, K2, K1) on this end +void tdea_cbc_payload_crypt (uint8_t * K1, uint8_t * K2, uint8_t * K3, uint8_t * iv, uint8_t * in, uint8_t * out, int16_t nblocks, uint8_t de) +{ + + int16_t i, j; + + //cipher input and output + uint8_t input_register[8]; memset(input_register, 0, sizeof(input_register)); + uint8_t output_register[8]; memset(output_register, 0, sizeof(output_register)); + + //load first round of input_register accordingly + if (de) + memcpy (input_register, iv, sizeof(input_register)); //load the IV as first input_register if encrypting + else memcpy (input_register, in, sizeof(input_register)); //load first cipher text as input_register is decrypting + + //run payload for number of payload nblocks required + for (i = 0; i < nblocks; i++) + { + + if (de) + { + + //xor the current input 'in' pt to the current state of the input_register for cbc feedback + for (j = 0; j < 8; j++) + input_register[j] ^= in[j+(i*8)]; + + //K1 + des_cipher(K1, input_register, output_register, de); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K2 + de = (de ^ 1) & 1; //flip the de bit + des_cipher(K2, input_register, output_register, de); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K3 + de = (de ^ 1) & 1; //flip the de bit back + des_cipher(K3, input_register, output_register, de); + memcpy (input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + + //copy ciphered output_register to output 'out' + memcpy (out+(i*8), output_register, sizeof(output_register)); + memset(output_register, 0, sizeof(output_register)); //reset output register + + } + else + { + + //K3 + des_cipher(K3, input_register, output_register, de); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K2 + de = (de ^ 1) & 1; //flip the de bit + des_cipher(K2, input_register, output_register, de); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K1 + de = (de ^ 1) & 1; //flip the de bit back + des_cipher(K1, input_register, output_register, de); + memcpy (input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + + //copy ciphered input_register to output 'out' + memcpy (out+(i*8), output_register, sizeof(output_register)); + + //xor the current output by IV, or by last received CT, depending on round + if (i == 0) + { + for (j = 0; j < 8; j++) + out[j] ^= iv[j]; + } + else + { + for (j = 0; j < 8; j++) + out[j+(i*8)] ^= in[j+((i-1)*8)]; + } + + //copy in next segment for input_register (if not last) + if (i < nblocks) + memcpy(input_register, in+((i+1)*8), sizeof(input_register)); + + memset(output_register, 0, sizeof(output_register)); //reset output register + } + + } + +} + +//TDEA, or triple data encryption algorithm, or triple DES, in cipher block chain mode (64-bit) +//same as usual inputs (byte wise), also, if needing DES56, just feed the same key into K1, K2, and K3 +//only the last output_register is returned for the variable len MAC bytes, always run in encryption mode +//but if iv is desireable, it will need to be pre-XOR'd with the first plaintext input block by the calling function +void tdea_cbc_mac_generator (uint8_t * K1, uint8_t * K2, uint8_t * K3, uint8_t * in, uint8_t * out, int16_t nblocks) +{ + + int16_t i, j; + + //cipher input and output + uint8_t input_register[8]; memset(input_register, 0, sizeof(input_register)); + uint8_t output_register[8]; memset(output_register, 0, sizeof(output_register)); + + //run payload for number of payload nblocks required + for (i = 0; i < nblocks; i++) + { + + //the cipher is always run in the foward, or encryption mode (1,0,1) + + //xor the current input 'in' pt to the current state of the input_register for cbc feedback + for (j = 0; j < 8; j++) + input_register[j] ^= in[j+(i*8)]; + + //K1 + des_cipher(K1, input_register, output_register, 1); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K2 + des_cipher(K2, input_register, output_register, 0); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K3 + des_cipher(K3, input_register, output_register, 1); + memcpy (input_register, output_register, sizeof(output_register)); + + //copy ciphered output_register to output 'out' + //Since we only want the last output_register, + //this will overwrite the out until completion + memcpy (out, output_register, sizeof(output_register)); + + memset(output_register, 0, sizeof(output_register)); //reset output register + + } + +} + +//TDEA, or triple data encryption algorithm, or triple DES, in cihper feedback mode (64-bit) +//same as usual inputs (byte wise), also, if needing DES56, just feed the same key into K1, K2, and K3 +void tdea_cfb_payload_crypt (uint8_t * K1, uint8_t * K2, uint8_t * K3, uint8_t * iv, uint8_t * in, uint8_t * out, int16_t nblocks, uint8_t de) +{ + + int16_t i, j; + + //cipher input and output + uint8_t input_register[8]; memset(input_register, 0, sizeof(input_register)); + uint8_t output_register[8]; memset(output_register, 0, sizeof(output_register)); + + //copy the IV to the input_register (make copy so we don't manipulate the calling functions copy) + memcpy(input_register, iv, sizeof(input_register)); + + //execute the des_cipher in output feedback mode 3 times using each key and transferring output to input each time + for (i = 0; i < nblocks; i++) + { + + //the cipher is always run in the foward, or encryption mode (1,0,1) + + //K1 + des_cipher(K1, input_register, output_register, 1); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K2 + des_cipher(K2, input_register, output_register, 0); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K3 + des_cipher(K3, input_register, output_register, 1); + + //xor the current input 'in' to the current state of the input_register for cipher feedback + for (j = 0; j < 8; j++) + output_register[j] ^= in[j+(i*8)]; + + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + + //copy keystream out and reset + memcpy(out+(i*8), output_register, sizeof(output_register)); //copy output_register to ks_bytes + iteration offset of times 8 + memset(output_register, 0, sizeof(output_register)); //reset output register + + //if running in decryption mode, we feed in the next round of input + if (!de) + memcpy(input_register, in+(i*8), sizeof(input_register)); + } + +} + +//TDEA, or triple data encryption algorithm, or triple DES, in IV counter mode (tested, working) +void tdea_ctr_payload_crypt (uint8_t * K1, uint8_t * K2, uint8_t * K3, uint8_t * iv, uint8_t * input, uint8_t * output, int16_t nblocks) +{ + + int16_t i, j; + + //cipher input and output + uint8_t input_register[8]; memset(input_register, 0, sizeof(input_register)); + uint8_t output_register[8]; memset(output_register, 0, sizeof(output_register)); + + //copy the IV to the input_register (ctr mode will manipulate the IV, since it needs to keep a rolling counter + memcpy(input_register, iv, sizeof(input_register)); + + //execute the des_cipher in counter mode 3 times using each key and transferring output to input each time + //then the IV is iterated and fed back into the input_register to start the next nblocks loop + for (i = 0; i < nblocks; i++) + { + + //CTR mode cipher should always run in the forward (encryption) mode + + //K1 + des_cipher(K1, input_register, output_register, 1); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K2 + des_cipher(K2, input_register, output_register, 0); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K3 + des_cipher(K3, input_register, output_register, 1); + + //set output at current pointer to the xor of input current pointer and the output_register + for (j = 0; j < 8; j++) + output[j+(i*8)] = input[j+(i*8)] ^ output_register[j]; + + memset(output_register, 0, sizeof(output_register)); //reset output register + + //increment the IV, and handle roll over (uint8_t will rollover to 0 after 0xFF) + for (j = 7; j >= 0; j--) + { + iv[j]++; + if (iv[j] == 0) + continue; + else break; + } + + //debug IV iteration + // fprintf (stderr, "\n IV: "); + // for (j = 0; j < 8; j++) + // fprintf (stderr, "%02X", iv[j]); + + //feed the new IV into the input register + memcpy (input_register, iv, sizeof(input_register)); + + } + +} + +//TDEA, or triple data encryption algorithm, or triple DES, in output feedback mode +void tdea_tofb_keystream_output (uint8_t * K1, uint8_t * K2, uint8_t * K3, uint8_t * iv, uint8_t * ks_bytes, uint8_t de, int16_t nblocks) +{ + + //cipher input and output + uint8_t input_register[8]; memset(input_register, 0, sizeof(input_register)); + uint8_t output_register[8]; memset(output_register, 0, sizeof(output_register)); + + //copy the IV to the input_register (make copy so we don't manipulate the calling functions copy) + memcpy(input_register, iv, sizeof(input_register)); + + //execute the des_cipher in output feedback mode 3 times using each key and transferring output to input each time + for (int16_t i = 0; i < nblocks; i++) + { + //K1 + des_cipher(K1, input_register, output_register, de); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K2 + de = (de ^ 1) & 1; //flip the de bit + des_cipher(K2, input_register, output_register, de); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + memset(output_register, 0, sizeof(output_register)); //reset output register + + //K3 + de = (de ^ 1) & 1; //flip the de bit back + des_cipher(K3, input_register, output_register, de); + memcpy(input_register, output_register, sizeof(output_register)); //recycle output_register back into input_register + + //copy keystream out and reset + memcpy(ks_bytes+(i*8), output_register, sizeof(output_register)); //copy output_register to ks_bytes + iteration offset of times 8 + memset(output_register, 0, sizeof(output_register)); //reset output register + } + +} + +//a linear feedback shift register with maximal taps on 64-bit values that can be run to any specified len, +//its input is a byte array of up to 8 bytes, and its output is same array packed with new LFSR value in it. +uint64_t lfsr_64_to_len_ca(uint8_t * iv, int16_t len) +{ + + uint64_t lfsr = 0, bit = 0; + + lfsr = ((uint64_t)iv[0] << 56ULL) + ((uint64_t)iv[1] << 48ULL) + ((uint64_t)iv[2] << 40ULL) + ((uint64_t)iv[3] << 32ULL) + + ((uint64_t)iv[4] << 24ULL) + ((uint64_t)iv[5] << 16ULL) + ((uint64_t)iv[6] << 8ULL) + ((uint64_t)iv[7] << 0ULL); + + memset (iv, 0, 8*sizeof(uint8_t)); + + for(int16_t cnt = 0; cnt < len; cnt++) + { + //63,61,45,37,27,14 + // Polynomial is C(x) = x^64 + x^62 + x^46 + x^38 + x^27 + x^15 + 1 + bit = ((lfsr >> 63) ^ (lfsr >> 61) ^ (lfsr >> 45) ^ (lfsr >> 37) ^ (lfsr >> 26) ^ (lfsr >> 14)) & 0x1; + lfsr = (lfsr << 1) | bit; + } + + for (int16_t i = 0; i < 8; i++) + iv[i] = (lfsr >> (56-(i*8))) & 0xFF; + + // fprintf (stderr, "\n IV(%02d): ", len); + // for (int16_t i = 0; i < 8; i++) + // fprintf (stderr, "%02X", iv[i]); + + return bit; + +} + +void des56_ca_keystream_output (uint8_t * main_key, uint8_t * iv, uint8_t * ks_bytes, uint8_t de, int16_t ff, int16_t nbits) +{ + + //cipher input and output + uint8_t input_register[8]; memset(input_register, 0, sizeof(input_register)); + uint8_t output_register[8]; memset(output_register, 0, sizeof(output_register)); + + //copy the IV to the input_register (make copy so we don't manipulate the calling functions copy) + memcpy(input_register, iv, sizeof(input_register)); + + //fast forward the current input_register state + lfsr_64_to_len_ca(input_register, ff); + + //execute the des_cipher in (CA) mode with 1-bit output + for (int16_t i = 0; i < nbits; i++) + { + + //de should be 1 here for encryption mode + des_cipher(main_key, input_register, output_register, de); + + //keystream accumulation, shift current byte and append + //single bit from current output register's most significant bit + ks_bytes[i/8] <<= 1; + ks_bytes[i/8] |= ((output_register[0] >> 7) & 1); + + //advance the input_register with the lfsr 1 time + lfsr_64_to_len_ca(input_register, 1); + + //reset output register + memset(output_register, 0, sizeof(output_register)); + + } + + // fprintf (stderr, "\n IR: "); + // for (int16_t i = 0; i < 8; i++) + // fprintf (stderr, "%02X", input_register[i]); + +} + +//transitional function mainly to load key and iv into an array +void des_multi_keystream_output (unsigned long long int mi, unsigned long long int key_ulli, uint8_t * output, int type, int len) +{ + int i = 0; + uint8_t iv[8]; memset (iv, 0, sizeof(iv)); + uint8_t key[8]; memset(key, 0, sizeof(key)); + + //convert unsinged long long int values into array values + for (i = 7; i >= 0; i--) + iv[7-i] = (mi >> (8*i)) & 0xFF; + + for (i = 7; i >= 0; i--) + key[7-i] = (key_ulli >> (8*i)) & 0xFF; + + //debug + // fprintf (stderr, "\n IV: "); + // for (i = 0; i < 8; i++) + // fprintf (stderr, "%02X", iv[i]); + // fprintf (stderr, "\n Key: "); + // for (i = 0; i < 8; i++) + // fprintf (stderr, "%02X", key[i]); + + //types: 1 = DES56 OFB; 2 = DES56 CA (XL) + if (type == 2) + { + if (len == 0) + des56_ca_keystream_output(key, iv, output, 1, 110+696, 1704); + else des56_ca_keystream_output(key, iv, output, 1, 110+000, 1704); + } + else des56_ofb_keystream_output(key, iv, output, 1, len); + +} + +//transitional function mainly to load iv into an array +void tdea_multi_keystream_output (unsigned long long int mi, uint8_t * key, uint8_t * output, int type, int len) +{ + int i = 0; + uint8_t iv[8]; memset (iv, 0, sizeof(iv)); + + //convert unsinged long long int values into array values + for (i = 7; i >= 0; i--) + iv[7-i] = (mi >> (8*i)) & 0xFF; + + //debug + // fprintf (stderr, "\n IV: "); + // for (i = 0; i < 8; i++) + // fprintf (stderr, "%02X", iv[i]); + + //type 1 = TDEA TOFB //TODO: Add more types like 2DES? + if (type == 1) + tdea_tofb_keystream_output(key, key+8, key+16, iv, output, 1, len); + else tdea_tofb_keystream_output(key, key+8, key+16, iv, output, 1, len); + +} \ No newline at end of file diff --git a/src/1.c b/src/crypt-rc4.c similarity index 54% rename from src/1.c rename to src/crypt-rc4.c index 1637ece..ca95944 100644 --- a/src/1.c +++ b/src/crypt-rc4.c @@ -1,13 +1,49 @@ /*------------------------------------------------------------------------------- - * 1.c - * RC4 and RC4 Block Output For Keystream Application - * - * - * + * rc4.c Crypthings + * RC4 Alg *-----------------------------------------------------------------------------*/ #include "dsd.h" +//this version is for voice, going to transition to a block output version +void rc4_voice_decrypt(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]; + + } + +} + //this is for PDU usage void rc4_block_output (int drop, int keylen, int meslen, uint8_t * key, uint8_t * output_blocks) { diff --git a/src/dmr_block.c b/src/dmr_block.c index f3818eb..ff64379 100644 --- a/src/dmr_block.c +++ b/src/dmr_block.c @@ -913,6 +913,7 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte if (end < 0) end = 3096; int alg = 0; int kid = 0; + int akl = 0; if (state->currentslot == 0) alg = state->payload_algid; else alg = state->payload_algidR; @@ -936,6 +937,21 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte else R = state->rkey_array[state->payload_keyidR]; + //loader for aes keys + uint8_t kaes[32]; + uint8_t empt[32]; + uint8_t maes[16]; + for (i = 0; i < 8; i++) + { + kaes[i+0] = ((state->rkey_array[kid+0x000]) >> (56-(i*8))) & 0xFF; + kaes[i+8] = ((state->rkey_array[kid+0x101]) >> (56-(i*8))) & 0xFF; + kaes[i+16] = ((state->rkey_array[kid+0x201]) >> (56-(i*8))) & 0xFF; + kaes[i+24] = ((state->rkey_array[kid+0x301]) >> (56-(i*8))) & 0xFF; + + //if kaes is loaded with a key, then flag on the key loaded variable + if (memcmp(kaes, empt, sizeof(kaes)) != 0) akl = 1; + } + if (R == 0 && state->R != 0) R = state->R; //easier to manually load up rather than make a loop (RC4) @@ -959,12 +975,47 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte if (alg == 4) fprintf (stderr, " AES256;"); if (R && alg != 0) fprintf (stderr, " Key: %010llX;", R); + //generate 128-bit IV from 32-bit MI + //expand 32-bit MI to 128-bit IV for AES mode data decryption + //we only want to do this at the moment of keystream generation + if (alg == 5) + { + fprintf (stderr, "\n"); + LFSR128d(state); + if (state->currentslot == 0) + memcpy (maes, state->aes_iv, sizeof(maes)); + if (state->currentslot == 1) + memcpy (maes, state->aes_ivR, sizeof(maes)); + } + if (alg == 1 && R != 0) //RC4 { rc4_block_output (256, 9, (int)state->data_byte_ctr[slot], kiv, ob); decrypted_pdu = 1; } + if (alg == 5 && akl == 1) //AES-256 + { + int nblocks = (state->data_byte_ctr[slot] / 16) + 1; + aes_ofb_keystream_output (maes, kaes, ob, 2, nblocks); + decrypted_pdu = 1; + } + + //other algs available, not sure if others will be used in any DMRA offerings + if (alg == 2 && R != 0) //Tait DES + { + int nblocks = (state->data_byte_ctr[slot] / 8) + 1; + des_multi_keystream_output (mi, R, ob, 1, nblocks); + decrypted_pdu = 1; + } + + if (alg == 4 && akl == 1) //AES-128 + { + int nblocks = (state->data_byte_ctr[slot] / 16) + 1; + aes_ofb_keystream_output (maes, kaes, ob, 0, nblocks); + 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! if (alg == 1 && R != 0) @@ -972,6 +1023,22 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte for (i = 0; i < end; i++) state->dmr_pdu_sf[slot][i+start] ^= ob[i%3096]; } + + else if (alg == 2 && R != 0) + { + for (i = 0; i < end; i++) + state->dmr_pdu_sf[slot][i+start] ^= ob[i%3096]; + } + else if (alg == 4 && akl != 0) + { + for (i = 0; i < end; i++) + state->dmr_pdu_sf[slot][i+start] ^= ob[i%3096]; + } + else if (alg == 5 && akl != 0) + { + for (i = 0; i < end; i++) + state->dmr_pdu_sf[slot][i+start] ^= ob[i%3096]; + } //BP key application else if (alg == 0) diff --git a/src/dmr_flco.c b/src/dmr_flco.c index 7cb716a..2bff90e 100644 --- a/src/dmr_flco.c +++ b/src/dmr_flco.c @@ -620,6 +620,26 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C fprintf (stderr, "Key %010llX ", state->RR); fprintf (stderr, "%s ", KNRM); } + + if (slot == 0 && (state->payload_algid == 0x25 || state->payload_algid == 0x24) && state->aes_key_loaded[0] == 1) + { + fprintf (stderr, "\n "); + fprintf (stderr, "%s", KYEL); + fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]); + if (state->payload_algid == 0x25) + fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]); + fprintf (stderr, "%s ", KNRM); + } + + if (slot == 1 && (state->payload_algidR == 0x25 || state->payload_algidR == 0x24) && state->aes_key_loaded[1] == 1) + { + fprintf (stderr, "\n "); + fprintf (stderr, "%s", KYEL); + fprintf (stderr, "Key: %016llX %016llX ", state->A1[1], state->A2[1]); + if (state->payload_algidR == 0x25) + fprintf (stderr, "%016llX %016llX", state->A3[1], state->A4[1]); + fprintf (stderr, "%s ", KNRM); + } } diff --git a/src/dmr_le.c b/src/dmr_le.c index 7a89fa5..68fcefd 100644 --- a/src/dmr_le.c +++ b/src/dmr_le.c @@ -115,12 +115,23 @@ void dmr_late_entry_mi (dsd_opts * opts, dsd_state * state) fprintf (stderr, "\n"); fprintf (stderr, "%s", KNRM); } - //run afterwards, or le verification won't match up properly - if (state->payload_algid != 0x21) + + //run expansions afterwards, or le verification won't match up properly + + //DES1 + if (state->payload_algid == 0x22) { LFSR64 (state); fprintf (stderr, "\n"); - } + } + + //AES-128 or AES-256 + if (state->payload_algid == 0x24 || state->payload_algid == 0x25) + { + LFSR128d (state); + fprintf (stderr, "\n"); + } + } if (slot == 1 && state->payload_algidR != 0) { @@ -134,16 +145,62 @@ void dmr_late_entry_mi (dsd_opts * opts, dsd_state * state) fprintf (stderr, "\n"); fprintf (stderr, "%s", KNRM); } - //run afterwards, or le verification won't match up properly - if (state->payload_algidR != 0x21) + + //run expansions afterwards, or le verification won't match up properly + + //DES1 + if (state->payload_algidR == 0x22) { LFSR64 (state); fprintf (stderr, "\n"); - } + } + + //AES-128 or AES-256 + if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25) + { + LFSR128d (state); + fprintf (stderr, "\n"); + } + } } + //run LFSR even if golay fails + else if (slot == 0 && state->payload_algid != 0) + { + //DES1 + if (state->payload_algid == 0x22) + { + LFSR64 (state); + fprintf (stderr, "\n"); + } + + //AES-128 or AES-256 + if (state->payload_algid == 0x24 || state->payload_algid == 0x25) + { + LFSR128d (state); + fprintf (stderr, "\n"); + } + } + else if (slot == 1 && state->payload_algidR != 0) + { + //DES1 + if (state->payload_algidR == 0x22) + { + LFSR64 (state); + fprintf (stderr, "\n"); + } + + //AES-128 or AES-256 + if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25) + { + LFSR128d (state); + fprintf (stderr, "\n"); + } + } + + } void dmr_alg_refresh (dsd_opts * opts, dsd_state * state) @@ -195,8 +252,8 @@ void dmr_alg_reset (dsd_opts * opts, dsd_state * state) state->dropR = 256; state->DMRvcL = 0; state->DMRvcR = 0; - state->payload_miP = 0; - state->payload_miN = 0; + // state->payload_miP = 0; //running these clears out before we can create a new keystream + // state->payload_miN = 0; //running these clears out before we can create a new keystream } //handle Single Burst (Voice Burst F) or Reverse Channel Signalling diff --git a/src/dmr_pi.c b/src/dmr_pi.c index 7542c61..1238522 100644 --- a/src/dmr_pi.c +++ b/src/dmr_pi.c @@ -38,15 +38,38 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC //Anytone RC4 Shim if (state->payload_algid == 0x01) { - fprintf (stderr, " Anytone (0x01)"); + fprintf (stderr, " Anytone RC4 (0x01)"); state->payload_algid = 0x21; } + //Anytone/Hytera AES-128 Shim + if (state->payload_algid == 0x04) + { + fprintf (stderr, " Anytone/Hytera AES-128 (0x04)"); + state->payload_algid = 0x24; + } + + //Anytone/Hytera AES-256 Shim + if (state->payload_algid == 0x05) + { + fprintf (stderr, " Anytone/Hytera AES-256 (0x05)"); + state->payload_algid = 0x25; + } + fprintf (stderr, "%s ", KNRM); - if (state->payload_algid != 0x21) + + //expand the 32-bit MI to a 64-bit DES1 IV + if (state->payload_algid == 0x22) { fprintf (stderr, "\n"); LFSR64 (state); + } + + //expand the 32-bit MI to a 128-bit AES IV + if (state->payload_algid == 0x24 || state->payload_algid == 0x25) + { + fprintf (stderr, "\n"); + LFSR128d (state); } } @@ -77,11 +100,34 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC state->payload_algidR = 0x21; } + //Anytone/Hytera AES-128 Shim + if (state->payload_algidR == 0x04) + { + fprintf (stderr, " Anytone/Hytera AES-128 (0x04)"); + state->payload_algidR = 0x24; + } + + //Anytone/Hytera AES-256 Shim + if (state->payload_algidR == 0x05) + { + fprintf (stderr, " Anytone/Hytera AES-256 (0x05)"); + state->payload_algidR = 0x25; + } + fprintf (stderr, "%s ", KNRM); - if (state->payload_algidR != 0x21) + + //expand the 32-bit MI to a 64-bit DES1 IV + if (state->payload_algidR == 0x22) { fprintf (stderr, "\n"); LFSR64 (state); + } + + //expand the 32-bit MI to a 128-bit AES IV + if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25) + { + fprintf (stderr, "\n"); + LFSR128d (state); } } @@ -120,7 +166,7 @@ void LFSR(dsd_state * state) fprintf (stderr, "%s", KYEL); fprintf (stderr, " Slot 1"); fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algid, state->payload_keyid); - fprintf(stderr, " MI: 0x%08X", lfsr); + fprintf(stderr, " MI(32): 0x%08X", lfsr); fprintf (stderr, "%s", KNRM); state->payload_mi = lfsr; } @@ -131,12 +177,13 @@ void LFSR(dsd_state * state) fprintf (stderr, "%s", KYEL); fprintf (stderr, " Slot 2"); fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algidR, state->payload_keyidR); - fprintf(stderr, " MI: 0x%08X", lfsr); + fprintf(stderr, " MI(32): 0x%08X", lfsr); fprintf (stderr, "%s", KNRM); state->payload_miR = lfsr; } } +//Expand a 32-bit MI into a 64-bit IV for DES void LFSR64(dsd_state * state) { { @@ -161,9 +208,11 @@ void LFSR64(dsd_state * state) fprintf (stderr, "%s", KYEL); fprintf (stderr, " Slot 1"); fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algid, state->payload_keyid); - fprintf (stderr, " MI: 0x%016llX", lfsr); + fprintf (stderr, " MI(64): 0x%016llX", lfsr); fprintf (stderr, "%s", KNRM); state->payload_mi = lfsr & 0xFFFFFFFF; //truncate for next repitition and le verification + state->payload_miP = lfsr; + state->DMRvcL = 0; } if (state->currentslot == 1) @@ -171,10 +220,94 @@ void LFSR64(dsd_state * state) fprintf (stderr, "%s", KYEL); fprintf (stderr, " Slot 2"); fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algidR, state->payload_keyidR); - fprintf (stderr, " MI: 0x%016llX", lfsr); + fprintf (stderr, " MI(64): 0x%016llX", lfsr); fprintf (stderr, "%s", KNRM); state->payload_miR = lfsr & 0xFFFFFFFF; //truncate for next repitition and le verification + state->payload_miN = lfsr; + state->DMRvcR = 0; } } +} + + +//Expand a 32-bit MI into a 128-bit IV for AES +void LFSR128d(dsd_state * state) +{ + unsigned long long int lfsr = 0; + + if (state->currentslot == 0) + lfsr = state->payload_mi; + else lfsr = state->payload_miR; + + unsigned long long int next_mi; + + //start packing aes_iv + if (state->currentslot == 0) + { + state->aes_iv[0] = (lfsr >> 24) & 0xFF; + state->aes_iv[1] = (lfsr >> 16) & 0xFF; + state->aes_iv[2] = (lfsr >> 8 ) & 0xFF; + state->aes_iv[3] = (lfsr >> 0 ) & 0xFF; + } + else if (state->currentslot == 1) + { + state->aes_ivR[0] = (lfsr >> 24) & 0xFF; + state->aes_ivR[1] = (lfsr >> 16) & 0xFF; + state->aes_ivR[2] = (lfsr >> 8 ) & 0xFF; + state->aes_ivR[3] = (lfsr >> 0 ) & 0xFF; + } + + int cnt = 0; int x = 32; + unsigned long long int bit; + for(cnt=0;cnt<96;cnt++) + { + //32,22,2,1 + bit = ( (lfsr >> 31) ^ (lfsr >> 21) ^ (lfsr >> 1) ^ (lfsr >> 0) ) & 0x1; + lfsr = (lfsr << 1) | bit; + + //continue packing aes_iv + if (state->currentslot == 0) + state->aes_iv[x/8] = (state->aes_iv[x/8] << 1) + bit; + else if (state->currentslot == 1) + state->aes_ivR[x/8] = (state->aes_ivR[x/8] << 1) + bit; + x++; + } + + //assign the next 32-bit short MI from 4,5,6,7 so it'll match up with OTA late entry + if (state->currentslot == 0) + next_mi = (state->aes_iv[4] << 24) + (state->aes_iv[5] << 16) + (state->aes_iv[6] << 8) + (state->aes_iv[7] << 0); + if (state->currentslot == 1) + next_mi = (state->aes_ivR[4] << 24) + (state->aes_ivR[5] << 16) + (state->aes_ivR[6] << 8) + (state->aes_ivR[7] << 0); + + if (state->currentslot == 0) + { + fprintf (stderr, "%s", KYEL); + fprintf (stderr, " Slot 1"); + fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X MI(128): ", state->payload_algid, state->payload_keyid); + for (x = 0; x < 16; x++) + fprintf (stderr, "%02X", state->aes_iv[x]); + fprintf (stderr, "%s", KNRM); + // fprintf (stderr, "\n"); + + state->payload_mi = next_mi; + state->DMRvcL = 0; + + } + + if (state->currentslot == 1) + { + fprintf (stderr, "%s", KYEL); + fprintf (stderr, " Slot 2"); + fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X MI(128): ", state->payload_algidR, state->payload_keyidR); + for (x = 0; x < 16; x++) + fprintf (stderr, "%02X", state->aes_ivR[x]); + fprintf (stderr, "%s", KNRM); + // fprintf (stderr, "\n"); + + state->payload_miR = next_mi; + state->DMRvcR = 0; + + } + } \ No newline at end of file diff --git a/src/dsd_audio2.c b/src/dsd_audio2.c index a93d72e..bab8028 100644 --- a/src/dsd_audio2.c +++ b/src/dsd_audio2.c @@ -93,13 +93,21 @@ void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state) encL = 0; } } - else if (state->payload_algid == 0x21) + else if (state->payload_algid == 0x21 || state->payload_algid == 0x22) { if (state->R != 0) { encL = 0; } } + else if (state->payload_algid == 0x24 || state->payload_algid == 0x25) + { + //going to need a better check for this later on, or seperated keys or something + if (state->aes_key_loaded[0] == 1) + { + encL = 0; + } + } } if (encR) @@ -111,15 +119,27 @@ void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state) encR = 0; } } - else if (state->payload_algidR == 0x21) + else if (state->payload_algidR == 0x21 || state->payload_algidR == 0x22) { if (state->RR != 0) { encR = 0; } } + else if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25) + { + //going to need a better check for this later on, or seperated keys or something + if (state->aes_key_loaded[1] == 1) + { + encR = 0; + } + } } + //debug disable enc check for AES testing + // encL = 0; + // encR = 0; + //TODO: add option to bypass enc with a toggle as well //CHEAT: Using the slot on/off, use that to set encL or encR back on @@ -312,6 +332,20 @@ void playSynthesizedVoiceFS4 (dsd_opts * opts, dsd_state * state) encL = 0; } } + else if (state->payload_algid == 0x81) + { + if (state->R != 0) + { + encL = 0; + } + } + else if (state->payload_algid == 0x84 || state->payload_algid == 0x89) + { + if (state->aes_key_loaded[0] == 1) + { + encL = 0; + } + } } if (encR) @@ -323,6 +357,20 @@ void playSynthesizedVoiceFS4 (dsd_opts * opts, dsd_state * state) encR = 0; } } + else if (state->payload_algidR == 0x81) + { + if (state->R != 0) + { + encR = 0; + } + } + else if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) + { + if (state->aes_key_loaded[1] == 1) + { + encR = 0; + } + } } //CHEAT: Using the slot on/off, use that to set encL or encR back on @@ -520,13 +568,20 @@ void playSynthesizedVoiceFS (dsd_opts * opts, dsd_state * state) //checkdown to see if we can lift the 'mute' if a key is available if (encL) { - if (state->payload_algid == 0xAA) + if (state->payload_algid == 0xAA || state->payload_algid == 0x81 || state->payload_algid == 0x9F) { if (state->R != 0) { encL = 0; } } + else if (state->payload_algid == 0x84 || state->payload_algid == 0x89 || state->payload_algid == 0x83) + { + if (state->aes_key_loaded[0] == 1) + { + encL = 0; + } + } } //TODO: add option to bypass enc with a toggle as well @@ -654,13 +709,20 @@ void playSynthesizedVoiceFM (dsd_opts * opts, dsd_state * state) //checkdown to see if we can lift the 'mute' if a key is available if (encL) { - if (state->payload_algid == 0xAA || state->nxdn_cipher_type == 0x1) + if (state->payload_algid == 0xAA || state->payload_algid == 0x81 || state->payload_algid == 0x83 || state->payload_algid == 0x9F || state->nxdn_cipher_type == 0x1 || state->nxdn_cipher_type == 0x2) { if (state->R != 0) { encL = 0; } } + else if (state->payload_algid == 0x84 || state->payload_algid == 0x89 || state->nxdn_cipher_type == 0x3) + { + if (state->aes_key_loaded[0] == 1) + { + encL = 0; + } + } } //WIP: Mute if on B list (or not W list) @@ -870,13 +932,20 @@ void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state) //checkdown to see if we can lift the 'mute' if a key is available if (encL) { - if (state->payload_algid == 0xAA) + if (state->payload_algid == 0xAA || state->payload_algid == 0x81 || state->payload_algid == 0x9F || state->payload_algid == 0x83) { if (state->R != 0) { encL = 0; } } + else if (state->payload_algid == 0x84 || state->payload_algid == 0x89) + { + if (state->aes_key_loaded[0] == 1) + { + encL = 0; + } + } } //TODO: add option to bypass enc with a toggle as well @@ -993,7 +1062,7 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state) encL = (state->dmr_so >> 6) & 0x1; encR = (state->dmr_soR >> 6) & 0x1; - //checkdown to see if we can lift the 'mute' if a key is available + //checkdown to see if we can lift the 'mute' if a key is available if (encL) { if (state->payload_algid == 0) @@ -1003,13 +1072,21 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state) encL = 0; } } - else if (state->payload_algid == 0x21) + else if (state->payload_algid == 0x21 || state->payload_algid == 0x22) { if (state->R != 0) { encL = 0; } } + else if (state->payload_algid == 0x24 || state->payload_algid == 0x25) + { + //going to need a better check for this later on, or seperated keys or something + if (state->aes_key_loaded[0] == 1) + { + encL = 0; + } + } } if (encR) @@ -1021,15 +1098,26 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state) encR = 0; } } - else if (state->payload_algidR == 0x21) + else if (state->payload_algidR == 0x21 || state->payload_algidR == 0x22) { if (state->RR != 0) { encR = 0; } } + else if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25) + { + //going to need a better check for this later on, or seperated keys or something + if (state->aes_key_loaded[1] == 1) + { + encR = 0; + } + } } + //debug for AES + // encL = encR = 0; + //TODO: add option to bypass enc with a toggle as well //CHEAT: Using the slot on/off, use that to set encL or encR back on @@ -1342,6 +1430,20 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state) encL = 0; } } + else if (state->payload_algid == 0x81) + { + if (state->R != 0) + { + encL = 0; + } + } + else if (state->payload_algid == 0x84 || state->payload_algid == 0x89) + { + if (state->aes_key_loaded[0] == 1) + { + encL = 0; + } + } } if (encR) @@ -1353,6 +1455,20 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state) encR = 0; } } + else if (state->payload_algidR == 0x81) + { + if (state->R != 0) + { + encR = 0; + } + } + else if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) + { + if (state->aes_key_loaded[1] == 1) + { + encR = 0; + } + } } @@ -1552,26 +1668,52 @@ void playSynthesizedVoiceSS18 (dsd_opts * opts, dsd_state * state) //checkdown to see if we can lift the 'mute' if a key is available if (encL) { - if (state->payload_algid == 0xAA) + //RC4 or DES + if (state->payload_algid == 0xAA || state->payload_algid == 0x81) { if (state->R != 0) { encL = 0; } } + + //AES + if (state->payload_algid == 0x84 || state->payload_algid == 0x89) + { + if (state->aes_key_loaded[0] == 1) + { + encL = 0; + } + } + } if (encR) { - if (state->payload_algidR == 0xAA) + //RC4 or DES + if (state->payload_algidR == 0xAA || state->payload_algidR == 0x81) { if (state->RR != 0) { encR = 0; } } + + //AES + if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) + { + if (state->aes_key_loaded[1] == 1) + { + encR = 0; + } + } + } + //debug, unmute both slots + // encL = 0; + // encR = 0; + //WIP: Mute if on B list (or not W list) char modeL[8]; sprintf (modeL, "%s", ""); diff --git a/src/dsd_file.c b/src/dsd_file.c index 6b91326..72dd332 100644 --- a/src/dsd_file.c +++ b/src/dsd_file.c @@ -632,4 +632,49 @@ void unpack_ambe (uint8_t * input, char * ambe) ambe[k++] = (input[i] >> 0) & 1; } ambe[48] = input[6] >> 7; +} + +//convert a user string into a uint8_t array +uint16_t parse_raw_user_string (char * input, uint8_t * output) +{ + //since we want this as octets, get strlen value, then divide by two + uint16_t len = strlen((const char*)input); + + uint8_t shift = 0; + + //if zero is returned, just do two + // if (len == 0) len = 2; + + //if zero, return as 0 len string + if (len == 0) return 0; + + //if odd number, then user didn't pass complete octets, + //add one to len value and set the shift flag to left shift + if (len&1) + { + shift = 1; + len++; + } + + //divide by two to get octet len + len /= 2; + + char octet_char[3]; + octet_char[2] = 0; + uint16_t k = 0; + uint16_t i = 0; + + for (i = 0; i < len; i++) + { + strncpy (octet_char, input+k, 2); + octet_char[2] = 0; + sscanf (octet_char, "%hhX", &output[i]); + + k += 2; + } + + //if we had an odd input value, then left shift the last octet 4 to make it flush + if (shift) output[len-1] <<= 4; + + return len; } \ No newline at end of file diff --git a/src/dsd_import.c b/src/dsd_import.c index 572895a..907ae43 100644 --- a/src/dsd_import.c +++ b/src/dsd_import.c @@ -214,7 +214,7 @@ int csvKeyImportDec(dsd_opts * opts, dsd_state * state) //multi-key support } //Hex Variant of Key Import -int csvKeyImportHex(dsd_opts * opts, dsd_state * state) //key import for rc4 keys +int csvKeyImportHex(dsd_opts * opts, dsd_state * state) //key import for hex keys { char filename[1024] = "filename.csv"; sprintf (filename, "%s", opts->key_in_file); @@ -247,10 +247,31 @@ int csvKeyImportHex(dsd_opts * opts, dsd_state * state) //key import for rc4 key sscanf (field, "%llX", &state->rkey_array[keynumber]); } + //this could also theoretically nuke other keys that are at the same offset + if (field_count == 2) + { + sscanf (field, "%llX", &state->rkey_array[keynumber+0x101]); + } + + if (field_count == 3) + { + sscanf (field, "%llX", &state->rkey_array[keynumber+0x201]); + } + + if (field_count == 4) + { + sscanf (field, "%llX", &state->rkey_array[keynumber+0x301]); + } + field = strtok(NULL, ","); field_count++; } + fprintf (stderr, "Key [%04llX] [%016llX]", keynumber, state->rkey_array[keynumber]); + + //if longer key is loaded (or clash with the 0x101, 0x201, 0x301 offset, then print the full key listing) + if ( (state->rkey_array[keynumber+0x101] != 0) || (state->rkey_array[keynumber+0x201] != 0) || (state->rkey_array[keynumber+0x301] != 0) ) + fprintf (stderr, " [%016llX] [%016llX] [%016llX]", state->rkey_array[keynumber+0x101], state->rkey_array[keynumber+0x201], state->rkey_array[keynumber+0x301]); fprintf (stderr, "\n"); } diff --git a/src/dsd_main.c b/src/dsd_main.c index 3a9091a..81d0cab 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -347,6 +347,21 @@ noCarrier (dsd_opts * opts, dsd_state * state) state->p25vc = 0; state->payload_miP = 0; + //ks array storage and counters + memset (state->ks_octetL, 0, sizeof(state->ks_octetL)); + memset (state->ks_octetR, 0, sizeof(state->ks_octetR)); + memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL)); + memset (state->ks_bitstreamR, 0, sizeof(state->ks_bitstreamR)); + state->octet_counter = 0; + state->bit_counterL = 0; + state->bit_counterR = 0; + + //xl specific, we need to know if the ESS is from HDU, or from LDU2 + state->xl_is_hdu = 0; + + //NXDN, when a new IV has arrived + state->nxdn_new_iv = 0; + //initialize dmr data header source state->dmr_lrrp_source[0] = 0; state->dmr_lrrp_source[1] = 0; @@ -412,7 +427,15 @@ noCarrier (dsd_opts * opts, dsd_state * state) state->R = 0; //NXDN, or RC4 (slot 1) state->RR = 0; //RC4 (slot 2) state->K = 0; //BP - state->K1 = 0; //tera 10 char BP + state->K1 = 0; //tera 10/32/64 char BP + state->K2 = 0; + state->K3 = 0; + state->K4 = 0; + memset (state->A1, 0, sizeof(state->A1)); + memset (state->A2, 0, sizeof(state->A2)); + memset (state->A3, 0, sizeof(state->A3)); + memset (state->A4, 0, sizeof(state->A4)); + memset (state->aes_key_loaded, 0, sizeof (state->aes_key_loaded)); state->H = 0; //shim for above } @@ -1020,9 +1043,34 @@ initState (dsd_state * state) state->dropL = 256; state->dropR = 256; - state->p25vc = 0; + //ks array storage and counters + memset (state->ks_octetL, 0, sizeof(state->ks_octetL)); + memset (state->ks_octetR, 0, sizeof(state->ks_octetR)); + memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL)); + memset (state->ks_bitstreamR, 0, sizeof(state->ks_bitstreamR)); + state->octet_counter = 0; + state->bit_counterL = 0; + state->bit_counterR = 0; + //AES Specific Variables + memset (state->aes_key, 0, sizeof(state->aes_key)); + memset (state->aes_iv, 0, sizeof(state->aes_iv)); + memset (state->aes_ivR, 0, sizeof(state->aes_ivR)); + memset (state->A1, 0, sizeof(state->A1)); + memset (state->A2, 0, sizeof(state->A2)); + memset (state->A3, 0, sizeof(state->A3)); + memset (state->A4, 0, sizeof(state->A4)); + memset (state->aes_key_loaded, 0, sizeof (state->aes_key_loaded)); + + //xl specific, we need to know if the ESS is from HDU, or from LDU2 + state->xl_is_hdu = 0; + + //NXDN, when a new IV has arrived + state->nxdn_new_iv = 0; + + state->p25vc = 0; state->payload_miP = 0; + state->payload_miN = 0; //initialize dmr data header source state->dmr_lrrp_source[0] = 0; @@ -1453,24 +1501,33 @@ usage () printf (" -b Manually Enter Basic Privacy Key (Decimal Value of Key Number)\n"); printf (" (NOTE: This used to be the 'K' option! \n"); printf ("\n"); - printf (" -H Manually Enter **tera 10/32/64 Char Basic Privacy Hex Key (see example below)\n"); + printf (" -H Manually Enter Hytera 10/32/64 Char Basic Privacy Hex Key (see example below)\n"); printf (" Encapulate in Single Quotation Marks; Space every 16 chars.\n"); printf (" -H 0B57935150 \n"); printf (" -H '736B9A9C5645288B 243AD5CB8701EF8A' \n"); printf (" -H '20029736A5D91042 C923EB0697484433 005EFC58A1905195 E28E9C7836AA2DB8' \n"); + printf ("\n"); //may move to using the rkey_array with an offset for additional key values + printf (" -H Manually Enter AES-128 or AES-256 Hex Key (see example below)\n"); + printf (" Encapulate in Single Quotation Marks; Space every 16 chars.\n"); + printf (" -H '736B9A9C5645288B 243AD5CB8701EF8A' \n"); + printf (" -H '20029736A5D91042 C923EB0697484433 005EFC58A1905195 E28E9C7836AA2DB8' \n"); printf ("\n"); printf (" -R Manually Enter dPMR or NXDN EHR Scrambler Key Value (Decimal Value)\n"); printf (" \n"); - printf (" -1 Manually Enter RC4 Key Value (DMR, P25) (Hex Value) \n"); + printf (" -1 Manually Enter RC4 or DES Key Value (DMR, P25, NXDN) (Hex Value) \n"); + printf (" \n"); + printf (" -2 Manually Enter TYT and Enforce 16-bit BP Key Value (DMR) (Hex Value) \n"); + printf (" \n"); + printf (" -5 Manually Enter 48-bit BP Key Value (DMR) (Hex Value) \n"); printf (" \n"); printf (" -k Import Key List from csv file (Decimal Format) -- Lower Case 'k'.\n"); printf (" Only supports NXDN, DMR Basic Privacy (decimal value). \n"); - printf (" (dPMR and **tera 32/64 char not supported, DMR uses TG value as key id -- EXPERIMENTAL!!). \n"); + printf (" (dPMR and Hytera 32/64 char not supported, DMR uses TG value as key id -- EXPERIMENTAL!!). \n"); printf (" \n"); printf (" -K Import Key List from csv file (Hexidecimal Format) -- Capital 'K'.\n"); - printf (" Use for Hex Value **tera 10-char BP keys and RC4 10-Char Hex Keys. \n"); + printf (" Use for Hex Value Hytera 10-char BP keys, RC4 10-char, DES 16-char Hex Keys, and AES128/256 32/64-char keys. \n"); printf (" \n"); - printf (" -4 Force Privacy Key over Encryption Identifiers (DMR BP and NXDN Scrambler) \n"); + printf (" -4 Force Privacy Key over Encryption Identifiers (DMR MBP/HBP and NXDN Scrambler) \n"); printf (" \n"); printf (" -0 Force RC4 Key over Missing PI header/LE Encryption Identifiers (DMR) \n"); printf (" \n"); @@ -1497,7 +1554,6 @@ usage () printf (" P25 - 12000; NXDN48 - 7000; NXDN96: 12000; DMR - 7000-12000; EDACS/PV - 12000-24000;\n"); //redo this, or check work, or whatever printf (" May vary based on system stregnth, etc.\n"); printf (" -t Set Trunking or Scan Speed VC/sync loss hangtime in seconds. (default = 1 second)\n"); - // printf (" -9 Force Enable EDACS Standard or Networked Mode if Auto Detection Fails \n"); printf ("\n"); printf (" Trunking Example TCP: dsd-fme -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N 2> log.ans\n"); printf (" Trunking Example RTL: dsd-fme -fs -i rtl:0:450M:26:-2:8 -T -C connect_plus_chan.csv -G group.csv -N 2> log.ans\n"); @@ -1699,11 +1755,6 @@ main (int argc, char **argv) char versionstr[25]; mbe_printVersion (versionstr); - #ifdef LIMAZULUTWEAKS - fprintf (stderr," Digital Speech Decoder: LimaZulu Edition VI\n"); - #else - fprintf (stderr," Digital Speech Decoder: Florida Man Edition\n"); - #endif for (short int i = 1; i < 7; i++) { fprintf (stderr,"%s\n", FM_banner[i]); } @@ -1801,15 +1852,31 @@ main (int argc, char **argv) fprintf (stderr,"Force RC4 Key over Missing PI header/LE Encryption Identifiers (DMR)\n"); break; - //load single rc4 key + //load single rc4/des key case '1': sscanf (optarg, "%llX", &state.R); state.RR = state.R; //put key on both sides - fprintf (stderr, "RC4 Encryption Key Value set to 0x%llX \n", state.R); + fprintf (stderr, "RC4/DES Encryption Key Value set to 0x%llX \n", state.R); opts.unmute_encrypted_p25 = 0; state.keyloader = 0; //turn off keyloader break; + //get user TYT BP Key and Force Its application + case '2': + state.M = 0x16; //16-bit TYT 'BP' Keys + sscanf (optarg, "%llX", &state.H); + state.H = state.H & 0xFFFF; //truncate to 16-bits + fprintf (stderr,"DMR TYT 16-bit Key %llX with Forced Application\n", state.H); + break; + + //Enter and Force Applicaiton of a a 48-bit AMBE Keystream (hex) for 'CCR' radios and weird 'BP' + case '5': + state.M = 0x48; //48-bit AMBE Keystream for any generic keystream application + sscanf (optarg, "%llX", &state.H); + state.H = state.H & 0xFFFFFFFFFFFF; //truncate to 48-bits + fprintf (stderr,"AMBE+2 48-bit Key %llX with Forced Application\n", state.H); + break; + case '3': opts.dmr_le = 0; fprintf (stderr,"DMR Late Entry Encryption Identifiers Disabled (VC6 Single Burst)\n"); @@ -2018,7 +2085,7 @@ main (int argc, char **argv) state.K2 = strtoull (pEnd, &pEnd, 16); state.K3 = strtoull (pEnd, &pEnd, 16); state.K4 = strtoull (pEnd, &pEnd, 16); - fprintf (stderr, "**tera Key = %016llX %016llX %016llX %016llX\n", state.K1, state.K2, state.K3, state.K4); + fprintf (stderr, "Hytera40/128/256 BP or AES128/256 Key = %016llX %016llX %016llX %016llX\n", state.K1, state.K2, state.K3, state.K4); opts.dmr_mute_encL = 0; opts.dmr_mute_encR = 0; if (state.K1 == 0 && state.K2 == 0 && state.K3 == 0 && state.K4 == 0) @@ -2027,6 +2094,15 @@ main (int argc, char **argv) opts.dmr_mute_encR = 1; } state.H = state.K1; //shim still required? + //load the AES keys into a seperate handler + state.A1[0] = state.A1[1] = state.K1; + state.A2[0] = state.A2[1] = state.K2; + state.A3[0] = state.A3[1] = state.K3; + state.A4[0] = state.A4[1] = state.K4; + //disable keyloader function + state.keyloader = 0; + //signal an aes key is loaded into each slot -- if no value presented, then this won't matter anyways + state.aes_key_loaded[0] = state.aes_key_loaded[1] = 1; break; case '4': @@ -2618,7 +2694,7 @@ main (int argc, char **argv) opts.pulse_digi_out_channels = 2; sprintf (opts.output_name, "DMR"); - fprintf (stderr,"Decoding DMR Stereo BS/MS Simplex\n"); + fprintf (stderr,"Decoding DMR BS/MS Simplex\n"); } //change ft to only do P25 and DMR (TDMA trunking modes) else if (optarg[0] == 't') @@ -2699,9 +2775,9 @@ main (int argc, char **argv) opts.dmr_stereo = 1; state.dmr_stereo = 0; //0 // opts.setmod_bw = 7000; - sprintf (opts.output_name, "DMR Stereo"); + sprintf (opts.output_name, "DMR"); fprintf (stderr,"-fr / DMR Mono switch has been deprecated.\n"); - fprintf (stderr,"Decoding DMR Stereo BS/MS Simplex\n"); + fprintf (stderr,"Decoding DMR BS/MS Simplex\n"); } else if (optarg[0] == 'm') diff --git a/src/dsd_mbe.c b/src/dsd_mbe.c index ea361f6..1edc5e9 100644 --- a/src/dsd_mbe.c +++ b/src/dsd_mbe.c @@ -29,41 +29,33 @@ void keyring(dsd_opts * opts, dsd_state * state) 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++) + //load any large keys (AES) + if (state->currentslot == 0) { - j = (j + S[i] + key[i % keylength]) % 256; - t = S[i]; - S[i] = S[j]; - S[j] = t; + state->A1[0] = state->rkey_array[state->payload_keyid+0x000]; + state->A2[0] = state->rkey_array[state->payload_keyid+0x101]; + state->A3[0] = state->rkey_array[state->payload_keyid+0x201]; + state->A4[0] = state->rkey_array[state->payload_keyid+0x301]; + + //check to see if there is a value loaded or not + if (state->A1[0] == 0 && state->A2[0] == 0 && state->A3[0] == 0 && state->A4[0] == 0) + state->aes_key_loaded[0] = 0; + else state->aes_key_loaded[0] = 1; + } - //Drop Bytes and Cipher Byte XOR - i = j = 0; - for(count = 0; count < (messagelength + drop); count++) + if (state->currentslot == 1) { - 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]; + state->A1[1] = state->rkey_array[state->payload_keyidR+0x000]; + state->A2[1] = state->rkey_array[state->payload_keyidR+0x101]; + state->A3[1] = state->rkey_array[state->payload_keyidR+0x201]; + state->A4[1] = state->rkey_array[state->payload_keyidR+0x301]; - //return mbe payload byte here - if (count >= drop) - plain[count - drop] = b^cipher[count - drop]; + //check to see if there is a value loaded or not + if (state->A1[1] == 0 && state->A2[1] == 0 && state->A3[1] == 0 && state->A4[1] == 0) + state->aes_key_loaded[1] = 0; + else state->aes_key_loaded[1] = 1; } @@ -261,6 +253,90 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a mbe_demodulateImbe7200x4400Data (imbe_fr); state->errs2 += mbe_eccImbe7200x4400Data (imbe_fr, imbe_d); + //P25p1 Multi Crypt Handler (DES1, DES3, DES-XL and AES) + if ( (state->payload_algid == 0x81 && state->R != 0) || //DES-56 + (state->payload_algid == 0x9F && state->R != 0) || //DES-XL + (state->payload_algid == 0x84 && state->aes_key_loaded[0] == 1) || + (state->payload_algid == 0x89 && state->aes_key_loaded[0] == 1) || + (state->payload_algid == 0x83 && state->aes_key_loaded[0] == 1) ) //3DES + { + uint8_t cipher[11]; + uint8_t plain[11]; + memset (cipher, 0, sizeof(cipher)); + memset (plain, 0, sizeof(plain)); + + uint8_t aes_key[32]; + memset (aes_key, 0, sizeof(aes_key)); + + //Load key from A1 - A4 + for (i = 0; i < 8; i++) + { + aes_key[i+0] = (state->A1[0] >> (56-(i*8))) & 0xFF; + aes_key[i+8] = (state->A2[0] >> (56-(i*8))) & 0xFF; + aes_key[i+16] = (state->A3[0] >> (56-(i*8))) & 0xFF; + aes_key[i+24] = (state->A4[0] >> (56-(i*8))) & 0xFF; + } + + if (state->p25vc == 0) + { + if (state->payload_algid == 0x81 || state->payload_algid == 0x83) //DES1 and DES3 + state->octet_counter = 11+8; //start on 19 for DES-OFB (8 discard + 8 LC + 3 reserved) + else if (state->payload_algid == 0x9F) + state->octet_counter = 11; //11 with info from LFSR run values (no discard) + else + state->octet_counter = 11+16; //start on 27 for AES (16 discard + 8 LC + 3 reserved) + memset (state->ks_octetL, 0, sizeof(state->ks_octetL)); + + //debug + // fprintf (stderr, "\n KO: %d; ", state->octet_counter); + + if (state->payload_algid == 0x81) //DES-56 + des_multi_keystream_output (state->payload_miP, state->R, state->ks_octetL, 1, 28); + if (state->payload_algid == 0x83) //3DES, or TDEA + tdea_multi_keystream_output (state->payload_miP, aes_key, state->ks_octetL, 1, 28); + if (state->payload_algid == 0x9F) //DES-XL + des_multi_keystream_output (state->payload_miP, state->R, state->ks_octetL, 2, state->xl_is_hdu); //hard coded bit count value, xl_is_hdu determines lfsr run values + if (state->payload_algid == 0x84) //AES256 + aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 2, 14); //14 + 1 discard round + if (state->payload_algid == 0x89) //AES128 + aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 0, 14); //14 + 1 discard round + + } + + int z = 0; int j = 0; + for (i = 0; i < 11; i++) + { + for (j = 0; j < 8; j++) + { + cipher[i] = cipher[i] << 1; + cipher[i] = cipher[i] + imbe_d[z]; + imbe_d[z] = 0; + z++; + } + } + + //debug output blocks + // fprintf (stderr, "\n OB:"); + for (i = 0; i < 11; i++) + { + // fprintf (stderr, " %02X", state->ks_octetL[state->octet_counter]); + plain[i] = cipher[i] ^ state->ks_octetL[state->octet_counter++]; + } + + z = 0; + for (i = 0; i < 11; i++) + { + for (j = 0; j < 8; j++) + { + imbe_d[z] = (plain[i] & 0x80) >> 7; + plain[i] = plain[i] << 1; + z++; + } + + } + + } + //P25p1 RC4 Handling if (state->payload_algid == 0xAA && state->R != 0) { @@ -313,7 +389,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a } } - RC4(state->dropL, 13, 11, rckey, cipher, plain); + rc4_voice_decrypt(state->dropL, 13, 11, rckey, cipher, plain); state->dropL += 11; z = 0; @@ -357,6 +433,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a if (opts->payload == 1) { PrintIMBEData (opts, state, imbe_d); + fprintf (stderr, " 7100"); } mbe_convertImbe7100to7200(imbe_d); @@ -388,7 +465,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a mbe_demodulateAmbe3600x2450Data (ambe_fr); state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d); - if ( (state->nxdn_cipher_type == 0x01 && state->R > 0) || + if ( (state->nxdn_cipher_type == 0x01 && state->R != 0) || (state->M == 1 && state->R > 0) ) { @@ -407,6 +484,68 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a } + //NXDN Generic Cipher 2 and Cipher 3 Keystream Application (to be tested) + else if ( (state->nxdn_cipher_type == 0x02 && state->R != 0) || + (state->nxdn_cipher_type == 0x03 && state->aes_key_loaded[0] == 1) ) + { + + if (state->nxdn_cipher_type == 0x02 && state->nxdn_new_iv == 1 && state->nxdn_part_of_frame == 0) + { + + //more debug + // fprintf (stderr, " IV: %016llX; Key: %016llX", state->payload_miN, state->R); + + memset (state->ks_octetL, 0, sizeof(state->ks_octetL)); + memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL)); + + des_multi_keystream_output (state->payload_miN, state->R, state->ks_octetL, 1, 26); //32 4V at 49 bits = 1568/64 = 24.5 + 1 discard block + + //reset bit_counter + state->bit_counterL = 0; + + //unpack the octets into a bit-wise keystream + unpack_byte_array_into_bit_array(state->ks_octetL+8, state->ks_bitstreamL, 26*8); + + //reset flag to 0 + state->nxdn_new_iv = 0; + + } + + //untested, but same setup as DES, so it 'SHOULD' work...maybe + if (state->nxdn_cipher_type == 0x03 && state->nxdn_new_iv == 1 && state->nxdn_part_of_frame == 0) + { + + //more debug + fprintf (stderr, " IV: %016llX; Key: %016llX", state->payload_miN, state->R); + + memset (state->ks_octetL, 0, sizeof(state->ks_octetL)); + memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL)); + + aes_ofb_keystream_output (state->aes_ivR, state->aes_key, state->ks_octetL, 2, 15); //14 + 1 discard round + + //reset bit_counter + state->bit_counterL = 0; + + //unpack the octets into a bit-wise keystream + unpack_byte_array_into_bit_array(state->ks_octetL+8, state->ks_bitstreamL, 15*8); + + //reset flag to 0 + state->nxdn_new_iv = 0; + + } + + //sanity check, don't exceed bit application counter + if (state->bit_counterL > (1568-49)) + state->bit_counterL = (1568-49); + + //Keystream creation is currently inside of the NXDN_decode_VCALL_IV function + for (i = 0; i < 49; i++) + ambe_d[i] ^= state->ks_bitstreamL[state->bit_counterL++]; + + // fprintf (stderr, " bc: %04d;", state->bit_counterL); //debug to see what the counter value is up to currently (seems nominal) + + } + 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); @@ -432,6 +571,53 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a mbe_demodulateAmbe3600x2450Data (ambe_fr); state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d); + //TYT (Tytera) 16-bit Key (Shuffle/Shift/Inversion Method) + if (state->M == 0x16) + { + //insert an expansion function here + unsigned long long int k = 0; + uint8_t pNT[56]; memset (pNT, 0, sizeof(pNT)); + + //I believe I have this one figured out now + //its just a shuffle, shift, invert, shift, invert, shift pattern + //could be an lfsr attached, but couldn't figure out the taps + + //below is the pattern found for the 16-bit keys listed on the right + // k = 0xFFFF00FFFF00; // 0xFFFF + // k = 0x3412CB1234ED; // 0x1234 + + //shuffle, invert, shift...and organize into proper key value + k = ((state->H & 0xFF) << 8) + ((state->H & 0xFF00) >> 8); + k = k << 8 | ((~(state->H & 0xFF) >> 0) & 0xFF); + k = k << 16 | state->H; + k = k << 8 | ((~(state->H & 0xFF00) >> 8) & 0xFF); + + //debug -- print 48-bit expanded key value + // fprintf (stderr, "K: %012llX", k); + + for (int j = 0; j < 48; j++) + { + x = ( ((k << j) & 0x800000000000) >> 47 ) & 1; + ambe_d[j] ^= x; + } + + } + + //Forced 48-bit Keystream Application "Quick and Dirty" XOR + if (state->M == 0x48) + { + // k = 0xD991633EC82E; //F811A5B94C2D ⊻ 2180C6878403 (1234 EP Key) + // k = 0x7F5363362BBE; //F811A5B94C2D ⊻ 8742C68F6793 (AAAA EP Key) + // k = 0x409231C77C08; (FFFF EP Key) + k = state->H; + for (int j = 0; j < 48; j++) //49 + { + x = ( ((k << j) & 0x800000000000) >> 47 ); + ambe_d[j] ^= x; + } + } + + //EXPERIMENTAL!! //load basic privacy key number from array by the tg value (if not forced) //currently only Moto BP and Hytera 10 Char BP @@ -535,6 +721,125 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a state->DMRvcL++; } + //DMR and P25p2 DES-OFB 56 Handling, Slot 1, VCH 0 -- consider moving into the AES handler + if ( (state->currentslot == 0 && state->payload_algid == 0x22 && state->R != 0) || + (state->currentslot == 0 && state->payload_algid == 0x81 && state->R != 0) ) + { + + //sanity check in case of error + if (state->DMRvcL > 17) state->DMRvcL = 17; + + int j; int z = 0; int n = 8; uint8_t b = 0; + if (state->DMRvcL == 0) + { + memset (state->ks_octetL, 0, sizeof(state->ks_octetL)); + memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL)); + state->bit_counterL = 0; + + //check all these comments I'm making for accuracy + des_multi_keystream_output (state->payload_miP, state->R, state->ks_octetL, 1, 19); //18 + 1 + + //Load Keystream Octet Bytes directly into a bit array, that way we don't have + //to keep track of the byte positions and masks for the 49th bit + for (i = 0; i < 18 * 8; i++) //19 blocks minus 1 discard block at 8 bits each + { + for (j = 0; j < 8; j++) + { + b = (( (state->ks_octetL[n] << j) & 0x80) >> 7); + state->ks_bitstreamL[z++] = b; + } + n++; + } + } + + //now we do the bit by bit xor depending on the frame and position of the state bit counter + //run 6 instead of 7 so we can just do bit 49 outside of loop to keep extra bits overloading the array + z = 0; + for (i = 0; i < 6; i++) + { + for (j = 0; j < 8; j++) + ambe_d[z++] ^= state->ks_bitstreamL[state->bit_counterL++]; + } + + //last bit + ambe_d[48] ^= state->ks_bitstreamL[state->bit_counterL++]; + + //skip the next 7 bits of the array + state->bit_counterL += 7; + + //increment vc counter by one + state->DMRvcL++; + + } + + //DMR and P25p2 AES 256, Slot 1, VCH 0 -- need a way to make sure we have a key when zero fill on some parts of it //&& state->aes_key_loaded[0] == 1 + if ( (state->currentslot == 0 && state->payload_algid == 0x24 && state->aes_key_loaded[0] == 1 ) || //DMR AES128 + (state->currentslot == 0 && state->payload_algid == 0x25 && state->aes_key_loaded[0] == 1 ) || //DMR AES256 + (state->currentslot == 0 && state->payload_algid == 0x89 && state->aes_key_loaded[0] == 1 ) || //P25 AES128 + (state->currentslot == 0 && state->payload_algid == 0x84 && state->aes_key_loaded[0] == 1) ) //P25 AES256 + { + + int j; int z = 0; int n = 16; uint8_t b = 0; //n=16 for AES-OFB discard round + uint8_t aes_key[32]; + memset (aes_key, 0, sizeof(aes_key)); + + //Load key from A1 - A4 + for (i = 0; i < 8; i++) + { + aes_key[i+0] = (state->A1[0] >> (56-(i*8))) & 0xFF; + aes_key[i+8] = (state->A2[0] >> (56-(i*8))) & 0xFF; + aes_key[i+16] = (state->A3[0] >> (56-(i*8))) & 0xFF; + aes_key[i+24] = (state->A4[0] >> (56-(i*8))) & 0xFF; + } + + //sanity check in case of error + if (state->DMRvcL > 17) state->DMRvcL = 17; + + if (state->DMRvcL == 0) + { + memset (state->ks_octetL, 0, sizeof(state->ks_octetL)); + memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL)); + state->bit_counterL = 0; + + if(state->payload_algid == 0x24 || state->payload_algid == 0x89) //AES128 + aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 0, 10); //9 + 1 discard round + if(state->payload_algid == 0x25 || state->payload_algid == 0x84) //AES256 + aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 2, 10); //9 + 1 discard round + + //Load Keystream Octet Bytes directly into keystream array + for (i = 0; i < 9 * 16; i++) //9 rounds at 16 octets + { + for (j = 0; j < 8; j++) + { + b = (( (state->ks_octetL[n] << j) & 0x80) >> 7); + state->ks_bitstreamL[z++] = b; + } + n++; + } + } + + //now we do the bit by bit xor depending on the frame and position of the state bit counter + //run 6 instead of 7 so we can just do bit 49 outside of loop to keep extra bits overloading the array + z = 0; + for (i = 0; i < 6; i++) + { + for (j = 0; j < 8; j++) + ambe_d[z++] ^= state->ks_bitstreamL[state->bit_counterL++]; + } + + //last bit + ambe_d[48] ^= state->ks_bitstreamL[state->bit_counterL++]; + + //skip the next 7 bits of the array + state->bit_counterL += 7; + + //increment vc counter by one + state->DMRvcL++; + + opts->dmr_mute_encL = 0; //shim to unmute + + } + //DMR RC4, Slot 1 if (state->currentslot == 0 && state->payload_algid == 0x21 && state->R != 0) { @@ -562,7 +867,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a //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); + rc4_voice_decrypt(state->dropL, 9, 7, rckey, cipher, plain); else memcpy (plain, cipher, sizeof(plain)); state->dropL += 7; @@ -602,7 +907,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a //pack cipher byte array from ambe_d bit array pack_ambe(ambe_d, cipher, 49); - RC4(state->dropL, 13, 7, rckey, cipher, plain); + rc4_voice_decrypt(state->dropL, 13, 7, rckey, cipher, plain); state->dropL += 7; //unpack deciphered plain array back into ambe_d bit array @@ -638,6 +943,52 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a mbe_demodulateAmbe3600x2450Data (ambe_fr); state->errs2R += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d); + //TYT (Tytera) 16-bit Key (Shuffle/Shift/Inversion Method) + if (state->M == 0x16) + { + //insert an expansion function here + unsigned long long int k = 0; + uint8_t pNT[56]; memset (pNT, 0, sizeof(pNT)); + + //I believe I have this one figured out now + //its just a shuffle, shift, invert, shift, invert, shift pattern + //could be an lfsr attached, but couldn't figure out the taps + + //below is the pattern found for the 16-bit keys listed on the right + // k = 0xFFFF00FFFF00; // 0xFFFF + // k = 0x3412CB1234ED; // 0x1234 + + //shuffle, invert, shift...and organize into proper key value + k = ((state->H & 0xFF) << 8) + ((state->H & 0xFF00) >> 8); + k = k << 8 | ((~(state->H & 0xFF) >> 0) & 0xFF); + k = k << 16 | state->H; + k = k << 8 | ((~(state->H & 0xFF00) >> 8) & 0xFF); + + //debug -- print 48-bit expanded key value + fprintf (stderr, "K: %012llX", k); + + for (int j = 0; j < 48; j++) + { + x = ( ((k << j) & 0x800000000000) >> 47 ) & 1; + ambe_d[j] ^= x; + } + + } + + //Forced 48-bit Keystream Application "Quick and Dirty" XOR + if (state->M == 0x48) + { + // k = 0xD991633EC82E; //F811A5B94C2D ⊻ 2180C6878403 (1234 EP Key) + // k = 0x7F5363362BBE; //F811A5B94C2D ⊻ 8742C68F6793 (AAAA EP Key) + // k = 0x409231C77C08; (FFFF EP Key) + k = state->H; + for (int j = 0; j < 48; j++) //49 + { + x = ( ((k << j) & 0x800000000000) >> 47 ); + ambe_d[j] ^= x; + } + } + //EXPERIMENTAL!! //load basic privacy key number from array by the tg value (if not forced) //currently only Moto BP and Hytera 10 Char BP @@ -741,6 +1092,125 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a state->DMRvcR++; } + //DMR and P25p2 DES-OFB 56 Handling, Slot 2, VCH 1 -- Consider moving into AES handler + if ( (state->currentslot == 1 && state->payload_algidR == 0x22 && state->RR != 0) || + (state->currentslot == 1 && state->payload_algidR == 0x81 && state->RR != 0) ) + { + + //sanity check in case of error + if (state->DMRvcR > 17) state->DMRvcR = 17; + + int j; int z = 0; int n = 8; uint8_t b = 0; + if (state->DMRvcR == 0) + { + memset (state->ks_octetR, 0, sizeof(state->ks_octetR)); + memset (state->ks_bitstreamR, 0, sizeof(state->ks_bitstreamR)); + state->bit_counterR = 0; + + //check all these comments I'm making for accuracy + des_multi_keystream_output (state->payload_miN, state->RR, state->ks_octetR, 1, 19); //18 + 1 + + //Load Keystream Octet Bytes directly into a bit array, that way we don't have + //to keep track of the byte positions and masks for the 49th bit + for (i = 0; i < 18 * 8; i++) //19 blocks minus 1 discard block at 8 bits each + { + for (j = 0; j < 8; j++) + { + b = (( (state->ks_octetR[n] << j) & 0x80) >> 7); + state->ks_bitstreamR[z++] = b; + } + n++; + } + } + + //now we do the bit by bit xor depending on the frame and position of the state bit counter + //run 6 instead of 7 so we can just do bit 49 outside of loop to keep extra bits overloading the array + z = 0; + for (i = 0; i < 6; i++) + { + for (j = 0; j < 8; j++) + ambe_d[z++] ^= state->ks_bitstreamR[state->bit_counterR++]; + } + + //last bit + ambe_d[48] ^= state->ks_bitstreamR[state->bit_counterR++]; + + //skip the next 7 bits of the array + state->bit_counterR += 7; + + //increment vc counter by one + state->DMRvcR++; + + } + + //DMR and P25p2 AES, Slot 2, VCH 1 + if ( (state->currentslot == 1 && state->payload_algidR == 0x24 && state->aes_key_loaded[1] == 1 ) || //DMR AES128 + (state->currentslot == 1 && state->payload_algidR == 0x25 && state->aes_key_loaded[1] == 1 ) || //DMR AES256 + (state->currentslot == 1 && state->payload_algidR == 0x89 && state->aes_key_loaded[1] == 1 ) || //P25 AES128 + (state->currentslot == 1 && state->payload_algidR == 0x84 && state->aes_key_loaded[1] == 1) ) //P25 AES256 + { + + int j; int z = 0; int n = 16; uint8_t b = 0; //n=16 for AES-OFB discard round + uint8_t aes_key[32]; + memset (aes_key, 0, sizeof(aes_key)); + + //Load key from A1 - A4 + for (i = 0; i < 8; i++) + { + aes_key[i+0] = (state->A1[1] >> (56-(i*8))) & 0xFF; + aes_key[i+8] = (state->A2[1] >> (56-(i*8))) & 0xFF; + aes_key[i+16] = (state->A3[1] >> (56-(i*8))) & 0xFF; + aes_key[i+24] = (state->A4[1] >> (56-(i*8))) & 0xFF; + } + + //sanity check in case of error + if (state->DMRvcR > 17) state->DMRvcR = 17; + + if (state->DMRvcR == 0) + { + memset (state->ks_octetR, 0, sizeof(state->ks_octetR)); + memset (state->ks_bitstreamR, 0, sizeof(state->ks_bitstreamR)); + state->bit_counterR = 0; + + if (state->payload_algidR == 0x24 || state->payload_algidR == 0x89) + aes_ofb_keystream_output (state->aes_ivR, aes_key, state->ks_octetR, 0, 10); //9 + 1 discard round + if (state->payload_algidR == 0x25 || state->payload_algidR == 0x84) + aes_ofb_keystream_output (state->aes_ivR, aes_key, state->ks_octetR, 2, 10); //9 + 1 discard round + + //Load Keystream Octet Bytes directly into keystream array + for (i = 0; i < 9 * 16; i++) //9 rounds at 16 octets + { + for (j = 0; j < 8; j++) + { + b = (( (state->ks_octetR[n] << j) & 0x80) >> 7); + state->ks_bitstreamR[z++] = b; + } + n++; + } + } + + //now we do the bit by bit xor depending on the frame and position of the state bit counter + //run 6 instead of 7 so we can just do bit 49 outside of loop to keep extra bits overloading the array + z = 0; + for (i = 0; i < 6; i++) + { + for (j = 0; j < 8; j++) + ambe_d[z++] ^= state->ks_bitstreamR[state->bit_counterR++]; + } + + //last bit + ambe_d[48] ^= state->ks_bitstreamR[state->bit_counterR++]; + + //skip the next 7 bits of the array + state->bit_counterR += 7; + + //increment vc counter by one + state->DMRvcR++; + + opts->dmr_mute_encR = 0; //shim to unmute + + } + //DMR RC4, Slot 2 if (state->currentslot == 1 && state->payload_algidR == 0x21 && state->RR != 0) { @@ -768,7 +1238,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a //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); + rc4_voice_decrypt(state->dropR, 9, 7, rckey, cipher, plain); else memcpy (plain, cipher, sizeof(plain)); state->dropR += 7; @@ -807,7 +1277,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a //pack cipher byte array from ambe_d bit array pack_ambe(ambe_d, cipher, 49); - RC4(state->dropR, 13, 7, rckey, cipher, plain); + rc4_voice_decrypt(state->dropR, 13, 7, rckey, cipher, plain); state->dropR += 7; //unpack deciphered plain array back into ambe_d bit array diff --git a/src/3.c b/src/dsd_misc.c similarity index 98% rename from src/3.c rename to src/dsd_misc.c index e104993..ae5e34a 100644 --- a/src/3.c +++ b/src/dsd_misc.c @@ -1,9 +1,9 @@ /*------------------------------------------------------------------------------- - * 3.c - * Placeholder File 3 -- This file is for temporary code storage + * dsd_misc.c + * Misc Code that needs to be reorganized and sorted out * - * Multiple 1/2 Rate Convolutional Decoders for NXDN/M17/YSF - * Used as a secondary decoder in case convolutional decoder fails (second opinion) + * + * *-----------------------------------------------------------------------------*/ #include "dsd.h" diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 0a76e06..a95e6c4 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -1192,24 +1192,26 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state) refresh(); } - //Privacy Key Entry + //Key Entry if (choice == 14) { state->payload_keyid = 0; state->payload_keyidR = 0; short int option = 0; - entry_win = newwin(14, WIDTH+6, starty+10, startx+10); + entry_win = newwin(16, WIDTH+6, starty+10, startx+10); box (entry_win, 0, 0); mvwprintw(entry_win, 2, 2, "Key Type Selection"); mvwprintw(entry_win, 3, 2, " "); mvwprintw(entry_win, 4, 2, "1 - Basic Privacy "); - mvwprintw(entry_win, 5, 2, "2 - **tera Privacy "); + mvwprintw(entry_win, 5, 2, "2 - Hytera Privacy "); mvwprintw(entry_win, 6, 2, "3 - NXDN/dPMR Scrambler "); mvwprintw(entry_win, 7, 2, "4 - Force BP/Scr Key Priority "); mvwprintw(entry_win, 8, 3, "-------------------------------- "); - mvwprintw(entry_win, 9, 2, "5 - RC4 Key "); - mvwprintw(entry_win, 10, 2, "6 - Force DMR RC4 Priority/LE "); - mvwprintw(entry_win, 11, 3, " "); + mvwprintw(entry_win, 9, 2, "5 - RC4 or DES Key "); + // mvwprintw(entry_win, 10, 2, "6 - Force DMR RC4 Priority/LE "); + mvwprintw(entry_win, 10, 2, "6 - AES-128 or AES-256 Key "); + mvwprintw(entry_win, 11, 3, "-------------------------------- "); + mvwprintw(entry_win, 14, 3, " "); echo(); refresh(); wscanw(entry_win, "%hd", &option); //%d @@ -1312,28 +1314,106 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state) state->R = 0; entry_win = newwin(6, WIDTH+6, starty+10, startx+10); box (entry_win, 0, 0); - mvwprintw(entry_win, 2, 2, "RC4 Key Value (HEX):"); + mvwprintw(entry_win, 2, 2, "RC4/DES Key Value (HEX):"); mvwprintw(entry_win, 3, 3, " "); echo(); refresh(); wscanw(entry_win, "%llX", &state->R); noecho(); - if (state->R > 0xFFFFFFFFFF) - { - state->R = 0xFFFFFFFFFF; - } + //disable size check for DES keys + // if (state->R > 0xFFFFFFFFFF) + // { + // state->R = 0xFFFFFFFFFF; + // } state->RR = state->R; //assign for both slots state->keyloader = 0; //turn off keyloader } //toggle enforcement of rc4 key over missing pi header/le on DMR + // if (option == 6) + // { + // if (state->M == 1 || state->M == 0x21) + // { + // state->M = 0; + // } + // else state->M = 0x21; + // } + + //load AES keys if (option == 6) { - if (state->M == 1 || state->M == 0x21) - { - state->M = 0; - } - else state->M = 0x21; + state->K1 = 0; + state->K2 = 0; + state->K3 = 0; + state->K4 = 0; + state->H = 0; + + memset (state->A1, 0, sizeof(state->A1)); + memset (state->A2, 0, sizeof(state->A2)); + memset (state->A3, 0, sizeof(state->A3)); + memset (state->A4, 0, sizeof(state->A4)); + + entry_win = newwin(7, WIDTH+8, starty+10, startx+10); + box (entry_win, 0, 0); + mvwprintw(entry_win, 2, 2, " Enter AES128/256 Key Value (HEX) "); + mvwprintw(entry_win, 3, 2, " First 16 Chars or Zero"); + mvwprintw(entry_win, 4, 3, " "); + echo(); + refresh(); + wscanw(entry_win, "%llX", &state->K1); + noecho(); + + entry_win = newwin(7, WIDTH+8, starty+10, startx+10); + box (entry_win, 0, 0); + // mvwprintw(entry_win, 2, 2, " Enter **tera Privacy Key Value 2 (HEX) "); + mvwprintw(entry_win, 3, 2, " Second 16 Chars or Zero"); + mvwprintw(entry_win, 4, 3, " "); + echo(); + refresh(); + wscanw(entry_win, "%llX", &state->K2); + noecho(); + + entry_win = newwin(7, WIDTH+8, starty+10, startx+10); + box (entry_win, 0, 0); + // mvwprintw(entry_win, 2, 2, " Enter **tera Privacy Key Value 3 (HEX) "); + mvwprintw(entry_win, 3, 2, " Third 16 Chars or Zero"); + mvwprintw(entry_win, 4, 3, " "); + echo(); + refresh(); + wscanw(entry_win, "%llX", &state->K3); + noecho(); + + entry_win = newwin(7, WIDTH+8, starty+10, startx+10); + box (entry_win, 0, 0); + // mvwprintw(entry_win, 2, 2, " Enter **tera Privacy Key Value 4 (HEX) "); + mvwprintw(entry_win, 3, 2, " Fourth 16 Chars or Zero"); + mvwprintw(entry_win, 4, 3, " "); + echo(); + refresh(); + wscanw(entry_win, "%llX", &state->K4); + noecho(); + + //load the AES keys into a seperate handler + state->A1[0] = state->A1[1] = state->K1; + state->A2[0] = state->A2[1] = state->K2; + state->A3[0] = state->A3[1] = state->K3; + state->A4[0] = state->A4[1] = state->K4; + + //zero out the K1-K4 + state->K1 = 0; + state->K2 = 0; + state->K3 = 0; + state->K4 = 0; + + state->keyloader = 0; //turn off keyloader + + //check to see if there is a value loaded or not + if (state->A1[0] == 0 && state->A2[0] == 0 && state->A3[0] == 0 && state->A4[0] == 0) + state->aes_key_loaded[0] = 0; + else state->aes_key_loaded[0] = 1; + + //mirror + state->aes_key_loaded[1] = state->aes_key_loaded[0]; } if (state->K == 0 && state->K1 == 0 && state->K2 == 0 && state->K3 == 0 && state->K4 == 0) @@ -2781,13 +2861,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) { if (state->R != 0) printw ("| Forcing Key Priority -- NXDN Sc Key: %05lld \n", state->R); if (state->K != 0) printw ("| Forcing Key Priority -- Moto BP Key: %03lld \n", state->K); - if (state->K1 != 0) printw ("| Forcing Key Priority -- tera BP Key: %016llX \n", state->K1); + if (state->K1 != 0) printw ("| Forcing Key Priority -- Hytera BP Key: %016llX \n", state->K1); if (state->K != 0 && state->K1 != 0) printw ("| Warning! Multiple DMR Key Types Loaded! \n"); //warning may not be required } if (state->M == 0x21) { if (state->R != 0) printw ("| Forcing Key Priority -- RC4 Key: %010llX \n", state->R); } + if (state->M == 0x16) printw ("| Forcing Key Priority -- TYT 16-bit Key: %04llX \n", state->H); if (opts->scanner_mode == 1) { @@ -2923,9 +3004,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if (state->m17_enc == 2) { - printw (" AES-CTR - IV: "); + attron(COLOR_PAIR(1)); + printw ("AES-CTR - IV: "); //display packed meta as IV - for (i = 0; i < 14; i++) + for (i = 0; i < 16; i++) printw ("%02X", state->m17_meta[i]); } @@ -3085,7 +3167,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("\n|"); if (state->nxdn_cipher_type > 0) { - printw (" ALG: [0x%02X] KEY: [0x%02X] ", state->nxdn_cipher_type, state->nxdn_key); + // printw (" ALG: %d Key ID: %02X ", state->nxdn_cipher_type, state->nxdn_key); + printw (" ALG: %d Key ID: %02d ", state->nxdn_cipher_type, state->nxdn_key); } if (state->nxdn_cipher_type == 0x1 && state->carrier == 1) { @@ -3096,26 +3179,28 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if (state->R != 0) { attron(COLOR_PAIR(1)); - printw ("KEY VALUE: [%05lld] ", state->R ); - printw ("SEED: [%04llX]", state->payload_miN); + printw ("Seed: %04llX ", state->payload_miN); + printw ("Key: %05lld ", state->R ); attron(COLOR_PAIR(3)); } } if (state->nxdn_cipher_type == 0x2 && state->carrier == 1) { attron(COLOR_PAIR(1)); - printw ("IV: [%016llX] ", state->payload_miN); + printw ("IV: %016llX ", state->payload_miN); attron(COLOR_PAIR(2)); printw ("DES1 "); + if (state->R != 0) printw ("Key: %016llX ", state->R); attroff(COLOR_PAIR(2)); attron(COLOR_PAIR(3)); } if (state->nxdn_cipher_type == 0x3 && state->carrier == 1) { attron(COLOR_PAIR(1)); - printw ("IV: [%016llX] ", state->payload_miN); + printw ("IV: %016llX ", state->payload_miN); attron(COLOR_PAIR(2)); printw ("AES-256 "); + if (state->aes_key_loaded[0] == 1) printw ("KS: %016llX", state->A4[0]); attroff(COLOR_PAIR(2)); attron(COLOR_PAIR(3)); } @@ -3268,32 +3353,32 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("| V XTRA | "); //10 spaces - if(state->dmrburstL == 16 && state->payload_algid == 0 && (state->dmr_so & 0xCF) == 0x40) //4F or CF mask? & 0xCF currently + if(state->dmrburstL == 16 && state->payload_algid == 0 && state->dmr_so & 0x40) //4F or CF mask? & 0xCF currently //&& (state->dmr_so & 0xCF) == 0x40 { attron(COLOR_PAIR(5)); - printw (" **Pr** "); + printw (" **BP** "); attroff(COLOR_PAIR(5)); attron(COLOR_PAIR(3)); } - if(state->dmrburstL == 16 && state->payload_algid == 0 && state->K > 0 && state->dmr_fid == 0x10 && (state->dmr_so & 0xCF) == 0x40) + if(state->dmrburstL == 16 && state->payload_algid == 0 && state->K > 0 && state->dmr_fid == 0x10 && state->dmr_so & 0x40) { attron(COLOR_PAIR(1)); - printw ("Pr Key [%3lld] ", state->K); + printw ("BP Key: %3lld ", state->K); attroff(COLOR_PAIR(1)); attron(COLOR_PAIR(3)); } - if(state->dmrburstL == 16 && state->payload_algid == 0 && state->H > 0 && state->dmr_fid == 0x68 && ((state->dmr_so & 0xCF) == 0x40) ) + if(state->dmrburstL == 16 && state->payload_algid == 0 && state->H > 0 && state->dmr_fid == 0x68 && state->dmr_so & 0x40) { attron(COLOR_PAIR(1)); - printw ("**tera Pr Key [%010llX] ", state->H); + printw ("Hytera BP Key: %010llX ", state->H); attroff(COLOR_PAIR(1)); attron(COLOR_PAIR(3)); } //ALG, KeyID, MI //was key_id - if(state->dmrburstL == 16 && state->payload_algid > 0 && (state->dmr_so & 0xCF) == 0x40) + if(state->dmrburstL == 16 && state->payload_algid > 0 && state->dmr_so & 0x40) { attron(COLOR_PAIR(1)); printw ("ALG: 0x%02X KEY: 0x%02X MI: 0x%08X ", state->payload_algid, state->payload_keyid, state->payload_mi); @@ -3322,6 +3407,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) { attron(COLOR_PAIR(1)); printw("DES1 "); + if (state->R != 0) { printw("Key: %010llX ", state->R); } + attron(COLOR_PAIR(3)); + } + if (state->payload_algid == 0x9F) + { + attron(COLOR_PAIR(1)); + printw("DES-XL "); + if (state->R != 0) { printw("Key: %010llX ", state->R); } attron(COLOR_PAIR(3)); } if (state->payload_algid == 0x82) @@ -3336,16 +3429,18 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw("DES3 "); attron(COLOR_PAIR(3)); } - if (state->payload_algid == 0x85 || state->payload_algid == 0x24) + if (state->payload_algid == 0x89 || state->payload_algid == 0x24) { attron(COLOR_PAIR(1)); - printw("AES-128"); + printw("AES-128 "); + if (state->aes_key_loaded[0] != 0) { printw("KS: %016llX ", state->A2[0]); } attron(COLOR_PAIR(3)); } if (state->payload_algid == 0x84 || state->payload_algid == 0x25 || state->payload_algid == 0x05) { attron(COLOR_PAIR(1)); - printw("AES-256"); + printw("AES-256 "); + if (state->aes_key_loaded[0] != 0) { printw("KS: %016llX ", state->A4[0]); } attron(COLOR_PAIR(3)); } if (state->payload_algid == 0x02) @@ -3468,30 +3563,30 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("| V XTRA | "); //10 spaces - if(state->dmrburstR == 16 && state->payload_algidR == 0 && (state->dmr_soR & 0xCF) == 0x40) //4F or CF mask? + if(state->dmrburstR == 16 && state->payload_algidR == 0 && state->dmr_soR & 0x40) //4F or CF mask? { attron(COLOR_PAIR(5)); - printw (" **Pr** "); + printw (" **BP** "); attroff(COLOR_PAIR(5)); attron(COLOR_PAIR(3)); } - if(state->dmrburstR == 16 && state->payload_algidR == 0 && state->K > 0 && ((state->dmr_soR & 0xCF) == 0x40) && state->dmr_fidR == 0x10) + if(state->dmrburstR == 16 && state->payload_algidR == 0 && state->K > 0 && state->dmr_soR & 0x40 && state->dmr_fidR == 0x10) { attron(COLOR_PAIR(1)); - printw ("Pr Key [%3lld] ", state->K); + printw ("BP Key: %3lld ", state->K); attroff(COLOR_PAIR(1)); attron(COLOR_PAIR(3)); } - if(state->dmrburstR == 16 && state->payload_algidR == 0 && state->H > 0 && ((state->dmr_soR & 0xCF) == 0x40) && state->dmr_fidR == 0x68) + if(state->dmrburstR == 16 && state->payload_algidR == 0 && state->H > 0 && state->dmr_soR & 0x40 && state->dmr_fidR == 0x68) { attron(COLOR_PAIR(1)); - printw ("**tera Pr Key [%010llX] ", state->H); + printw ("Hytera BP Key: %010llX ", state->H); attroff(COLOR_PAIR(1)); attron(COLOR_PAIR(3)); } //ALG, KeyID, MI 2 //was keyidR - if(state->dmrburstR == 16 && state->payload_algidR > 0 && (state->dmr_soR & 0xCF) == 0x40) + if(state->dmrburstR == 16 && state->payload_algidR > 0 && state->dmr_soR & 0x40) { attron(COLOR_PAIR(1)); printw ("ALG: 0x%02X KEY: 0x%02X MI: 0x%08X ", state->payload_algidR, state->payload_keyidR, state->payload_miR); @@ -3519,6 +3614,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) { attron(COLOR_PAIR(1)); printw("DES1 "); + if (state->RR != 0) { printw("Key: %010llX ", state->RR); } + attron(COLOR_PAIR(3)); + } + if (state->payload_algidR == 0x9F) + { + attron(COLOR_PAIR(1)); + printw("DES-XL "); + if (state->RR != 0) { printw("Key: %010llX ", state->RR); } attron(COLOR_PAIR(3)); } if (state->payload_algidR == 0x82) @@ -3533,16 +3636,18 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw("DES3 "); attron(COLOR_PAIR(3)); } - if (state->payload_algidR == 0x85 || state->payload_algidR == 0x24) + if (state->payload_algidR == 0x89 || state->payload_algidR == 0x24) { attron(COLOR_PAIR(1)); - printw("AES-128"); + printw("AES-128 "); + if (state->aes_key_loaded[1] != 0) { printw("KS: %016llX ", state->A2[1]); } attron(COLOR_PAIR(3)); } if (state->payload_algidR == 0x84 || state->payload_algidR == 0x25 || state->payload_algidR == 0x05) { attron(COLOR_PAIR(1)); - printw("AES-256"); + printw("AES-256 "); + if (state->aes_key_loaded[1] != 0) { printw("KS: %016llX ", state->A4[1]); } attron(COLOR_PAIR(3)); } if (state->payload_algidR == 0x02) @@ -3710,11 +3815,11 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) { if (opts->p25_is_tuned == 0) { - printw ("| Monitoring Control Channel\n"); + printw ("| Monitoring CC - LCN [%02d]\n", state->edacs_cc_lcn); } else { - printw ("| Monitoring Voice Channel - LCN [%02d]\n", state->edacs_tuned_lcn); + printw ("| Monitoring VC - LCN [%02d]", state->edacs_tuned_lcn); //since we are tuned, keep updating the time so it doesn't disappear during call call_matrix[state->edacs_tuned_lcn][5] = time(NULL); } diff --git a/src/nxdn_deperm.c b/src/nxdn_deperm.c index 304da1e..e3e6ff1 100644 --- a/src/nxdn_deperm.c +++ b/src/nxdn_deperm.c @@ -266,6 +266,9 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60]) if (state->nxdn_last_ran != -1) fprintf (stderr, " RAN %02d ", state->nxdn_last_ran); else fprintf (stderr, " "); + //needed for DES and AES + state->nxdn_part_of_frame = 0; + uint8_t nsf_sacch[26]; memset (nsf_sacch, 0, sizeof(nsf_sacch)); for (int i = 0; i < 26; i++) @@ -327,6 +330,9 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60]) else if (sf == 0) part_of_frame = 3; else part_of_frame = 0; + //needed for DES and AES + state->nxdn_part_of_frame = part_of_frame; + fprintf (stderr, "%s", KCYN); if (state->nxdn_last_ran != -1) fprintf (stderr, " RAN %02d ", state->nxdn_last_ran); else fprintf (stderr, " "); diff --git a/src/nxdn_element.c b/src/nxdn_element.c index a542e79..4d8ed38 100644 --- a/src/nxdn_element.c +++ b/src/nxdn_element.c @@ -1264,8 +1264,11 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message) if (state->rkey_array[KeyID] != 0) state->R = state->rkey_array[KeyID]; else if (state->rkey_array[DestinationID] != 0) state->R = state->rkey_array[DestinationID]; - //Don't zero key if no keyloader - if (CipherType != 0x1 && state->keyloader == 1) state->R = 0; + //Don't zero key if no keyloader, if we need this, do it when its nots NXDN96, causes issue when 96 VCALL comes in on all data frames + // if (CipherType != 0x1 && state->keyloader == 1) state->R = 0; //what did this do again? for mont system or something? + + //safe alternative? + if (CipherType == 0 && state->keyloader == 1) state->R = 0; /* Print the "Cipher Type" */ if(CipherType != 0 && MessageType == 0x1) @@ -1289,6 +1292,20 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message) fprintf (stderr, "%s", KNRM); } + if (CipherType == 0x02 && state->R > 0) //DES key value + { + fprintf (stderr, "%s", KYEL); + fprintf(stderr, "Value: %016llX", state->R); + fprintf (stderr, "%s", KNRM); + } + + if (CipherType == 0x03 && state->R > 0) //AES key stub + { + fprintf (stderr, "%s", KYEL); + fprintf(stderr, "KS: %016llX", state->R); + fprintf (stderr, "%s", KNRM); + } + //only grab if VCALL if(MessageType == 0x1) { @@ -1373,11 +1390,60 @@ void NXDN_decode_VCALL_IV(dsd_opts * opts, dsd_state * state, uint8_t * Message) //At this point, I would assume an LFSR function is needed to expand the 22-bit IV collected here into a 64-bit IV, or 128-bit IV state->payload_miN = IV; - state->NxdnElementsContent.PartOfCurrentEncryptedFrame = 2; - state->NxdnElementsContent.PartOfNextEncryptedFrame = 1; - fprintf (stderr, "\n VCALL_IV: %016llX", state->payload_miN); + + if ( ((state->nxdn_cipher_type == 0x02) || (state->nxdn_cipher_type == 0x03)) ) + { + + if (state->nxdn_cipher_type == 0x03 && state->keyloader == 1) + { + state->A1[0] = state->rkey_array[state->nxdn_key+0x000]; + state->A2[0] = state->rkey_array[state->nxdn_key+0x101]; + state->A3[0] = state->rkey_array[state->nxdn_key+0x201]; + state->A4[0] = state->rkey_array[state->nxdn_key+0x301]; + + //check to see if there is a value loaded or not + if (state->A1[0] == 0 && state->A2[0] == 0 && state->A3[0] == 0 && state->A4[0] == 0) + state->aes_key_loaded[0] = 0; + else state->aes_key_loaded[0] = 1; + + for (int i = 0; i < 8; i++) + { + state->aes_key[i+0] = (state->A1[0] >> (56-(i*8))) & 0xFF; + state->aes_key[i+8] = (state->A2[0] >> (56-(i*8))) & 0xFF; + state->aes_key[i+16] = (state->A3[0] >> (56-(i*8))) & 0xFF; + state->aes_key[i+24] = (state->A4[0] >> (56-(i*8))) & 0xFF; + } + + state->R = state->A1[0]; //display KS stub + + } + + //use the P25 Slot 1 LFSR128 to generate a 128-bit IV (state->payload_miN is on slot1) + if (state->nxdn_cipher_type == 0x03) + { + state->currentslot = 1; //quickly change to slot 1 + fprintf (stderr, "\n NXDN -- "); + LFSR128(state); //TODO: Make a different function so we don't see the LDU2/ESS-B info and null key values, or something + state->currentslot = 0; //change back to slot 0 + } + + if (state->nxdn_cipher_type == 0x02 && state->keyloader == 1) + { + if (state->rkey_array[state->nxdn_key] != 0) + state->R = state->rkey_array[state->nxdn_key]; + } + + //signal a new IV is available, but only when the other checks pass + if (state->nxdn_cipher_type == 0x02 && state->R != 0) + state->nxdn_new_iv = 1; + + if (state->nxdn_cipher_type == 0x03 && state->aes_key_loaded[0] == 1) + state->nxdn_new_iv = 1; + + } + } /* End NXDN_decode_VCALL_IV() */ //SCCH messages have a unique format that can be used in a super frame, but each 'unit' diff --git a/src/nxdn_frame.c b/src/nxdn_frame.c index 8408351..968a76f 100644 --- a/src/nxdn_frame.c +++ b/src/nxdn_frame.c @@ -432,6 +432,10 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state) } } + //correct the bit counter if NXDN96 Data Frames (or double FACCH1 steal) + if (state->nxdn_cipher_type == 0x2 || state->nxdn_cipher_type == 0x3) + state->bit_counterL += (49*4); + } if (voice && facch == 1) //facch steal 1 -- before voice @@ -453,6 +457,10 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state) LFSRN(ambe_temp, ambe_d, state); } } + + //correct the bit counter if FACCH1 steal) + if (state->nxdn_cipher_type == 0x2 || state->nxdn_cipher_type == 0x3) + state->bit_counterL += 49*2; } if (lich == 0x20 || lich == 0x21 || lich == 0x61 || lich == 0x40 || lich == 0x41) state->nxdn_sacch_non_superframe = TRUE; @@ -525,6 +533,10 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state) LFSRN(ambe_temp, ambe_d, state); } } + + //correct the bit counter if FACCH1 steal) + if (state->nxdn_cipher_type == 0x2 || state->nxdn_cipher_type == 0x3) + state->bit_counterL += 49*2; } if (opts->payload == 1 && !voice) fprintf (stderr, "\n"); diff --git a/src/p25p1_hdu.c b/src/p25p1_hdu.c index 515c780..5a4aee8 100644 --- a/src/p25p1_hdu.c +++ b/src/p25p1_hdu.c @@ -473,11 +473,32 @@ processHDU(dsd_opts* opts, dsd_state* state) fprintf (stderr, " HDU ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX", algidhex, kidhex, mihex1, mihex2); state->payload_algid = algidhex; state->payload_keyid = kidhex; + if (mihex3) fprintf (stderr, "-%02llX", mihex3); if (state->R != 0 && state->payload_algid == 0xAA) { fprintf (stderr, " Key: %010llX", state->R); opts->unmute_encrypted_p25 = 1; } + else if (state->R != 0 && state->payload_algid == 0x81) + { + fprintf (stderr, " Key: %010llX", state->R); + opts->unmute_encrypted_p25 = 1; + } + else if (state->R != 0 && state->payload_algid == 0x9F) + { + fprintf (stderr, " Key: %010llX", state->R); + opts->unmute_encrypted_p25 = 1; + } + else if ( (state->payload_algid == 0x84 || state->payload_algid == 0x89) && state->aes_key_loaded[0] == 1) + { + fprintf (stderr, "\n "); + fprintf (stderr, "%s", KYEL); + fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]); + if (state->payload_algid == 0x84) + fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]); + fprintf (stderr, "%s ", KNRM); + opts->unmute_encrypted_p25 = 1; + } else if (state->payload_algid != 0 && state->payload_algid != 0x80) { //may want to mute this again, or may not want to @@ -495,6 +516,17 @@ processHDU(dsd_opts* opts, dsd_state* state) } fprintf (stderr, "\n"); + + //expand 64-bit MI to 128-bit for AES + if (state->payload_algid == 0x84 || state->payload_algid == 0x89) + { + LFSR128(state); + fprintf (stderr, "\n"); + } + + //xl, we need to know if the ESS is from HDU, or LDU2 + state->xl_is_hdu = 1; + } else { diff --git a/src/p25p1_ldu1.c b/src/p25p1_ldu1.c index 2950a71..a9b7a61 100644 --- a/src/p25p1_ldu1.c +++ b/src/p25p1_ldu1.c @@ -49,6 +49,9 @@ processLDU1 (dsd_opts* opts, dsd_state* state) // so we start counter at 36-14-1 = 21 status_count = 21; + //set vc counter to 0 -- just playing it safe, shouldn't matter since rotating MIs are only in the LDU2 frame + state->p25vc = 0; + if (opts->errorbars == 1) { //fprintf (stderr, "e:"); @@ -253,6 +256,8 @@ processLDU1 (dsd_opts* opts, dsd_state* state) // TODO: do something useful with the LSD bytes... <--THIS! state->dropL += 2; //need to skip 2 here for the LSD bytes + //same for octet counter + state->octet_counter += 2; } // IMBE 9 diff --git a/src/p25p1_ldu2.c b/src/p25p1_ldu2.c index 86b15b2..a1e5e69 100644 --- a/src/p25p1_ldu2.c +++ b/src/p25p1_ldu2.c @@ -256,6 +256,9 @@ processLDU2 (dsd_opts * opts, dsd_state * state) // TODO: do something useful with the LSD bytes... <--THIS! state->dropL += 2; //need to skip 2 here for the LSD bytes + //same for octet counter + state->octet_counter += 2; + } // IMBE 9 @@ -277,6 +280,8 @@ processLDU2 (dsd_opts * opts, dsd_state * state) //reset dropbytes -- skip first 11 for next LCW state->dropL = 267; + //reset octet counter + state->octet_counter = 0; if (opts->errorbars == 1) { @@ -476,11 +481,38 @@ processLDU2 (dsd_opts * opts, dsd_state * state) fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX", algidhex, kidhex, mihex1, mihex2); state->payload_algid = algidhex; state->payload_keyid = kidhex; + if (mihex3) fprintf (stderr, "-%02llX", mihex3); if (state->R != 0 && state->payload_algid == 0xAA) { fprintf (stderr, " Key: %010llX", state->R); opts->unmute_encrypted_p25 = 1; } + else if (state->R != 0 && state->payload_algid == 0x81) + { + fprintf (stderr, " Key: %010llX", state->R); + opts->unmute_encrypted_p25 = 1; + } + else if (state->R != 0 && state->payload_algid == 0x9F) + { + fprintf (stderr, " Key: %010llX", state->R); + opts->unmute_encrypted_p25 = 1; + } + /* //going to want to update this for OFB, CBC, and ECB + { 0x84, "AES-256-OFB" }, + { 0x85, "AES-128-ECB"}, + { 0x88, "AES-CBC"}, + { 0x89, "AES-128-OFB"}, + */ + else if ( (state->payload_algid == 0x84 || state->payload_algid == 0x89) && state->aes_key_loaded[0] == 1) + { + fprintf (stderr, "\n "); + fprintf (stderr, "%s", KYEL); + fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]); + if (state->payload_algid == 0x84) + fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]); + fprintf (stderr, "%s ", KNRM); + opts->unmute_encrypted_p25 = 1; + } else if (state->payload_algid != 0 && state->payload_algid != 0x80) { //may want to mute this again, or may not want to @@ -627,6 +659,15 @@ processLDU2 (dsd_opts * opts, dsd_state * state) fprintf (stderr, "\n"); } + //expand 64-bit MI to 128-bit for AES + if (state->payload_algid == 0x84 || state->payload_algid == 0x89) + { + LFSR128(state); + fprintf (stderr, "\n"); + } + + //xl, we need to know if the ESS is from HDU, or LDU2 + state->xl_is_hdu = 0; #define P25p1_ENC_LO //disable if this behavior is detremental #ifdef P25p1_ENC_LO @@ -703,3 +744,86 @@ void LFSRP(dsd_state * state) fprintf (stderr, "\n LDU2/ESS_B FEC ERR - ALG: 0x%02X KEY ID: 0x%04X LFSR MI: 0x%016llX", state->payload_algidR, state->payload_keyidR, state->payload_miN); fprintf (stderr, "%s", KNRM); } + +void LFSR128(dsd_state * state) +{ + //generate a 128-bit IV from a 64-bit IV for AES blocks + unsigned long long int lfsr = 0; + + int slot = state->currentslot; + + if (state->currentslot == 0) + lfsr = state->payload_miP; + else lfsr = state->payload_miN; + + //start packing aes_iv + if (slot == 0) + { + state->aes_iv[0] = (lfsr >> 56) & 0xFF; + state->aes_iv[1] = (lfsr >> 48) & 0xFF; + state->aes_iv[2] = (lfsr >> 40) & 0xFF; + state->aes_iv[3] = (lfsr >> 32) & 0xFF; + state->aes_iv[4] = (lfsr >> 24) & 0xFF; + state->aes_iv[5] = (lfsr >> 16) & 0xFF; + state->aes_iv[6] = (lfsr >> 8 ) & 0xFF; + state->aes_iv[7] = (lfsr >> 0 ) & 0xFF; + } + if (slot == 1) + { + state->aes_ivR[0] = (lfsr >> 56) & 0xFF; + state->aes_ivR[1] = (lfsr >> 48) & 0xFF; + state->aes_ivR[2] = (lfsr >> 40) & 0xFF; + state->aes_ivR[3] = (lfsr >> 32) & 0xFF; + state->aes_ivR[4] = (lfsr >> 24) & 0xFF; + state->aes_ivR[5] = (lfsr >> 16) & 0xFF; + state->aes_ivR[6] = (lfsr >> 8 ) & 0xFF; + state->aes_ivR[7] = (lfsr >> 0 ) & 0xFF; + } + + int cnt = 0; int x = 64; + unsigned long long int bit; + //polynomial P(x) = 1 + X15 + X27 + X38 + X46 + X62 + X64 + for(cnt=0;cnt<64;cnt++) + { + //63,61,45,37,27,14 + // Polynomial is C(x) = x^64 + x^62 + x^46 + x^38 + x^27 + x^15 + 1 + bit = ((lfsr >> 63) ^ (lfsr >> 61) ^ (lfsr >> 45) ^ (lfsr >> 37) ^ (lfsr >> 26) ^ (lfsr >> 14)) & 0x1; + lfsr = (lfsr << 1) | bit; + + //continue packing aes_iv + if (slot == 0) + state->aes_iv[x/8] = (state->aes_iv[x/8] << 1) + bit; + if (slot == 1) + state->aes_ivR[x/8] = (state->aes_ivR[x/8] << 1) + bit; + x++; + } + + if (state->currentslot == 0) + { + fprintf (stderr, "%s", KYEL); + if (state->dmrburstL != 27) //if not LDU2 + fprintf (stderr, "\n"); + fprintf (stderr, " "); + fprintf (stderr, " ALG ID: 0x%02X KEY ID: 0x%04X MI(128): 0x", state->payload_algid, state->payload_keyid); + for (x = 0; x < 16; x++) + fprintf (stderr, "%02X", state->aes_iv[x]); + fprintf (stderr, "%s", KNRM); + // fprintf (stderr, "\n"); + + } + + if (state->currentslot == 1) + { + fprintf (stderr, "%s", KYEL); + if (state->dmrburstL != 27) //if not LDU2, shouldn't matter on P25p2 for the second slot + fprintf (stderr, "\n"); + fprintf (stderr, " "); + fprintf (stderr, " ALG ID: 0x%02X KEY ID: 0x%04X MI(128): 0x", state->payload_algidR, state->payload_keyidR); + for (x = 0; x < 16; x++) + fprintf (stderr, "%02X", state->aes_ivR[x]); + fprintf (stderr, "%s", KNRM); + // fprintf (stderr, "\n"); + + } + +} diff --git a/src/p25p1_pdu_data.c b/src/p25p1_pdu_data.c index de935ec..47af54c 100644 --- a/src/p25p1_pdu_data.c +++ b/src/p25p1_pdu_data.c @@ -62,20 +62,192 @@ void p25_decode_sap(uint8_t SAP, char * sap_string) } +void lfsr_64_to_128(uint8_t * iv) +{ + uint64_t lfsr = 0, bit = 0; + + lfsr = ((uint64_t)iv[0] << 56ULL) + ((uint64_t)iv[1] << 48ULL) + ((uint64_t)iv[2] << 40ULL) + ((uint64_t)iv[3] << 32ULL) + + ((uint64_t)iv[4] << 24ULL) + ((uint64_t)iv[5] << 16ULL) + ((uint64_t)iv[6] << 8ULL) + ((uint64_t)iv[7] << 0ULL); + + uint8_t cnt = 0, x = 64; + + for(cnt = 0;cnt < 64; cnt++) + { + //63,61,45,37,27,14 + // Polynomial is C(x) = x^64 + x^62 + x^46 + x^38 + x^27 + x^15 + 1 + bit = ((lfsr >> 63) ^ (lfsr >> 61) ^ (lfsr >> 45) ^ (lfsr >> 37) ^ (lfsr >> 26) ^ (lfsr >> 14)) & 0x1; + lfsr = (lfsr << 1) | bit; + + //continue packing iv + iv[x/8] = (iv[x/8] << 1) + bit; + + x++; + } + +} + uint8_t p25_decrypt_pdu(dsd_opts * opts, dsd_state * state, uint8_t * input, uint8_t alg_id, uint16_t key_id, unsigned long long int mi, int len) { + UNUSED(opts); uint8_t encrypted = 1; - UNUSED(opts); - UNUSED(state); - UNUSED(input); - UNUSED(mi); - UNUSED(key_id); - UNUSED(alg_id); - UNUSED(len); + int i = 0; + int ks_idx = 0; + uint8_t ks_bytes[3096]; memset (ks_bytes, 0, sizeof(ks_bytes)); + //create keystream + if (alg_id == 0x84 || alg_id == 0x89) //AES -- dsd-fme -f1 -i '/SSD_STORAGE/2024_DEV/otar shit/OTAR/SUGARLOAF DATA OUTPUT/CC-DSDPlus-Raw-Input_2024-08-27@134540.wav' -s 96000 -K testaeskeys.csv + { + //aes specific arrays and things + uint8_t aes_iv[16]; memset (aes_iv, 0, sizeof(aes_iv)); + uint8_t aes_key[32]; memset (aes_key, 0, sizeof(aes_key)); + uint8_t empt[64]; memset (empt, 0, sizeof(empt)); + + uint8_t akl = 0; //aes key loaded into array flag + unsigned long long int a1 = state->rkey_array[key_id+0x000]; + unsigned long long int a2 = state->rkey_array[key_id+0x101]; + unsigned long long int a3 = state->rkey_array[key_id+0x201]; + unsigned long long int a4 = state->rkey_array[key_id+0x301]; + + //checkdown to see if anything in a1-a4 + if ( (a1 == 0) && (a2 == 0) && (a3 == 0) && (a4 == 0) ) + { + //try loading from state->H instead (could clash if keys loaded that trigger any a1-a4 above) + a1 = state->K1; + a2 = state->K2; + a3 = state->K3; + a4 = state->K4; + } + + //loader for aes keys + for (uint64_t i = 0; i < 8; i++) + { + aes_key[i+0] = (a1 >> (56ULL-(i*8))) & 0xFF; + aes_key[i+8] = (a2 >> (56ULL-(i*8))) & 0xFF; + aes_key[i+16] = (a3 >> (56ULL-(i*8))) & 0xFF; + aes_key[i+24] = (a4 >> (56ULL-(i*8))) & 0xFF; + } + + //check to see if a key is loaded into any part of the array + if (memcmp(aes_key, empt, sizeof(aes_key)) != 0) akl = 1; + else akl = 0; + + //convert mi to aes_iv and expand it + aes_iv[0] = ((mi & 0xFF00000000000000) >> 56); + aes_iv[1] = ((mi & 0xFF000000000000) >> 48); + aes_iv[2] = ((mi & 0xFF0000000000) >> 40); + aes_iv[3] = ((mi & 0xFF00000000) >> 32); + aes_iv[4] = ((mi & 0xFF000000) >> 24); + aes_iv[5] = ((mi & 0xFF0000) >> 16); + aes_iv[6] = ((mi & 0xFF00) >> 8); + aes_iv[7] = ((mi & 0xFF) >> 0); + + lfsr_64_to_128(aes_iv); + + ks_idx = 16; //offset for OFB discard round + + if (akl == 1) + { + int nblocks = (len / 16) + 1; + if (alg_id == 0x84) //AES256 + aes_ofb_keystream_output (aes_iv, aes_key, ks_bytes, 2, nblocks); + else aes_ofb_keystream_output (aes_iv, aes_key, ks_bytes, 0, nblocks); + + fprintf (stderr, "\n Key: "); + for (i = 0; i < 32; i++) + { + if ( (i != 0) && ((i%8) == 0) ) + fprintf (stderr, " "); + fprintf (stderr, "%02X", aes_key[i]); + } + + encrypted = 0; + } + + fprintf (stderr, "\n IV(128): "); + for (i = 0; i < 16; i++) + fprintf (stderr, "%02X", aes_iv[i]); + + } + + if (alg_id == 0x81) //DES56 + { + + int nblocks = (len / 8) + 1; + unsigned long long int des_key = 0; + + des_key = state->rkey_array[key_id]; + + //if no key loaded from loader, check state->R for key + if (des_key == 0) des_key = state->R; + + ks_idx = 8; //offset for OFB discard round + + if (des_key) + des_multi_keystream_output (mi, des_key, ks_bytes, 1, nblocks); + + encrypted = 0; + + //debug, print key, iv, and keystream stuff + fprintf (stderr, "\n Key: %16llX", des_key); + + } + + if (alg_id == 0xAA) //RC4, or 'ADP' + { + + unsigned long long int rc4_key = 0; + + rc4_key = state->rkey_array[key_id]; + + //if no key loaded from loader, check state->R for key + if (rc4_key == 0) rc4_key = state->R; + + ks_idx = 0; //offset + + uint8_t rc4_kiv[13]; memset (rc4_kiv, 0, sizeof(rc4_key)); + + rc4_kiv[0] = ((rc4_key & 0xFF00000000) >> 32); + rc4_kiv[1] = ((rc4_key & 0xFF000000) >> 24); + rc4_kiv[2] = ((rc4_key & 0xFF0000) >> 16); + rc4_kiv[3] = ((rc4_key & 0xFF00) >> 8); + rc4_kiv[4] = ((rc4_key & 0xFF) >> 0); + + rc4_kiv[5] = ((mi & 0xFF00000000000000) >> 56); + rc4_kiv[6] = ((mi & 0xFF000000000000) >> 48); + rc4_kiv[7] = ((mi & 0xFF0000000000) >> 40); + rc4_kiv[8] = ((mi & 0xFF00000000) >> 32); + rc4_kiv[9] = ((mi & 0xFF000000) >> 24); + rc4_kiv[10] = ((mi & 0xFF0000) >> 16); + rc4_kiv[11] = ((mi & 0xFF00) >> 8); + rc4_kiv[12] = ((mi & 0xFF) >> 0); + + if (rc4_key) + rc4_block_output (256, 13, len, rc4_kiv, ks_bytes); + + encrypted = 0; + + //debug, print key, iv, and keystream stuff + fprintf (stderr, "\n Key: %16llX", rc4_key); + + } + + //debug input offset + // fprintf (stderr, "\n INPUT: "); + // for (i = 0; i < 16; i++) + // fprintf (stderr, "%02X", input[i]); + + // fprintf (stderr, "\n KS: "); + // for (i = 0; i < 16; i++) + // fprintf (stderr, "%02X", ks_bytes[i]); + + //apply keystream + for (i = 0; i < len; i++) //need to subtract pad bytes and crc bytes from keystream application + input[i] ^= ks_bytes[i+ks_idx]; + + if (alg_id == 0x80) encrypted = 0; return encrypted; } diff --git a/src/p25p2_frame.c b/src/p25p2_frame.c index 4bacb1a..dce904e 100644 --- a/src/p25p2_frame.c +++ b/src/p25p2_frame.c @@ -597,7 +597,7 @@ void process_ESS (dsd_opts * opts, dsd_state * state) if (opts->payload == 1) { - fprintf (stderr, "\n"); + // fprintf (stderr, "\n"); fprintf (stderr, " VCH %d - ESS_B %08llX%016llX ERR = %02d", state->currentslot, essb_hex1, essb_hex2, ec); } @@ -610,12 +610,30 @@ void process_ESS (dsd_opts * opts, dsd_state * state) state->payload_miP = ((essb_hex1 & 0xFF) << 56) | ((essb_hex2 & 0xFFFFFFFFFFFFFF00) >> 8); if (state->payload_algid != 0x80 && state->payload_algid != 0x0) { - fprintf (stderr, "\n VCH 0 -"); - fprintf (stderr, " ALG ID 0x%02X", state->payload_algid); - fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid); - fprintf (stderr, " MI 0x%016llX", state->payload_miP); - if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R); + fprintf (stderr, "\n"); + fprintf (stderr, " VCH 0 -"); + fprintf (stderr, " ALG ID: 0x%02X", state->payload_algid); + fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyid); + fprintf (stderr, " MI: 0x%016llX", state->payload_miP); fprintf (stderr, " ESSB"); + + if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R); + if (state->R != 0 && state->payload_algid == 0x81) fprintf (stderr, " Key 0x%016llX", state->R); + if ( (state->payload_algid == 0x84 || state->payload_algid == 0x89) && state->aes_key_loaded[0] == 1) + { + fprintf (stderr, "\n "); + fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]); + if (state->payload_algid == 0x84) + fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]); + // opts->unmute_encrypted_p25 = 1; //needed? + } + + //expand 64-bit MI to 128-bit for AES + if (state->payload_algid == 0x84 || state->payload_algid == 0x89) + { + LFSR128(state); + // fprintf (stderr, "\n"); + } } } @@ -626,12 +644,31 @@ void process_ESS (dsd_opts * opts, dsd_state * state) state->payload_miN = ((essb_hex1 & 0xFF) << 56) | ((essb_hex2 & 0xFFFFFFFFFFFFFF00) >> 8); if (state->payload_algidR != 0x80 && state->payload_algidR != 0x0) { - fprintf (stderr, "\n VCH 1 -"); - fprintf (stderr, " ALG ID 0x%02X", state->payload_algidR); - fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR); - fprintf (stderr, " MI 0x%016llX", state->payload_miN); - if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR); + fprintf (stderr, "\n"); + fprintf (stderr, " VCH 1 -"); + fprintf (stderr, " ALG ID: 0x%02X", state->payload_algidR); + fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyidR); + fprintf (stderr, " MI: 0x%016llX", state->payload_miN); fprintf (stderr, " ESSB"); + + if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR); + if (state->RR != 0 && state->payload_algidR == 0x81) fprintf (stderr, " Key 0x%016llX", state->RR); + if ( (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) && state->aes_key_loaded[1] == 1) + { + fprintf (stderr, "\n "); + fprintf (stderr, "Key: %016llX %016llX ", state->A1[1], state->A2[1]); + if (state->payload_algidR == 0x84) + fprintf (stderr, "%016llX %016llX", state->A3[1], state->A4[1]); + // opts->unmute_encrypted_p25 = 1; //needed? + } + + //expand 64-bit MI to 128-bit for AES + if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) + { + LFSR128(state); + // fprintf (stderr, "\n"); + } + } } @@ -702,11 +739,28 @@ void process_ESS (dsd_opts * opts, dsd_state * state) } if (ec == -1 || ec >= 15) { + //below needs a line break before LFSRP runs (when payload == 0) //ESS R-S Failure -- run LFSR on current MI if applicable if (state->currentslot == 0 && state->payload_algid != 0x80 && state->payload_keyid != 0 && state->payload_miP != 0) LFSRP(state); if (state->currentslot == 1 && state->payload_algidR != 0x80 && state->payload_keyidR != 0 && state->payload_miN != 0) LFSRP(state); + + //expand 64-bit MI to 128-bit for AES, vch 0 + // if (state->currentslot == 0 && state->payload_algid == 0x84 || state->payload_algid == 0x89) //old version + if (state->currentslot == 0 && (state->payload_algid == 0x84 || state->payload_algid == 0x89)) + { + LFSR128(state); + // fprintf (stderr, "\n"); + } + + //expand 64-bit MI to 128-bit for AES, vch 1 + // if (state->currentslot == 1 && state->payload_algidR == 0x84 || state->payload_algidR == 0x89) //old version if break + if (state->currentslot == 1 && (state->payload_algidR == 0x84 || state->payload_algidR == 0x89)) //new version with parenthesis + { + LFSR128(state); + // fprintf (stderr, "\n"); + } } fprintf (stderr, "%s", KNRM); @@ -817,6 +871,27 @@ void process_2V (dsd_opts * opts, dsd_state * state) if (state->currentslot == 1 && state->payload_algidR == 0xAA) state->dropR = 256; + //reset voice counter after 2V (DES) + if (state->currentslot == 0 && state->payload_algid == 0x81) + state->DMRvcL = 0; + + if (state->currentslot == 1 && state->payload_algidR == 0x81) + state->DMRvcR = 0; + + //reset voice counter after 2V (AES 256) + if (state->currentslot == 0 && state->payload_algid == 0x84) + state->DMRvcL = 0; + + if (state->currentslot == 1 && state->payload_algidR == 0x84) + state->DMRvcR = 0; + + //reset voice counter after 2V (AES 128) + if (state->currentslot == 0 && state->payload_algid == 0x89) + state->DMRvcL = 0; + + if (state->currentslot == 1 && state->payload_algidR == 0x89) + state->DMRvcR = 0; + } //P2 Data Unit ID diff --git a/src/p25p2_xcch.c b/src/p25p2_xcch.c index bccd89b..fc0b94b 100644 --- a/src/p25p2_xcch.c +++ b/src/p25p2_xcch.c @@ -153,11 +153,28 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180] if (state->payload_algid != 0x80 && state->payload_algid != 0x0) { fprintf (stderr, "%s", KYEL); - fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid); - fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid); - fprintf (stderr, " MI 0x%016llX", state->payload_miP); - if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R); + fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algid); + fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyid); + fprintf (stderr, " MI: 0x%016llX", state->payload_miP); fprintf(stderr, " MPTT"); + if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R); + if (state->R != 0 && state->payload_algid == 0x81) fprintf (stderr, " Key 0x%016llX", state->R); + + if ( (state->payload_algid == 0x84 || state->payload_algid == 0x89) && state->aes_key_loaded[0] == 1) + { + fprintf (stderr, "\n "); + fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]); + if (state->payload_algid == 0x84) + fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]); + // opts->unmute_encrypted_p25 = 1; //needed? + } + + //expand 64-bit MI to 128-bit for AES + if (state->payload_algid == 0x84 || state->payload_algid == 0x89) + { + LFSR128(state); + // fprintf (stderr, "\n"); + } // fprintf (stderr, " %s", KRED); // fprintf (stderr, "ENC"); } @@ -195,11 +212,28 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180] if (state->payload_algidR != 0x80 && state->payload_algidR != 0x0) { fprintf (stderr, "%s", KYEL); - fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR); - fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR); - fprintf (stderr, " MI 0x%016llX", state->payload_miN); - if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR); + fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algidR); + fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyidR); + fprintf (stderr, " MI: 0x%016llX", state->payload_miN); fprintf(stderr, " MPTT"); + + if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR); + if (state->RR != 0 && state->payload_algidR == 0x81) fprintf (stderr, " Key 0x%016llX", state->RR); + if ( (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) && state->aes_key_loaded[1] == 1) + { + fprintf (stderr, "\n "); + fprintf (stderr, "Key: %016llX %016llX ", state->A1[1], state->A2[1]); + if (state->payload_algidR == 0x84) + fprintf (stderr, "%016llX %016llX", state->A3[1], state->A4[1]); + // opts->unmute_encrypted_p25 = 1; //needed? + } + + //expand 64-bit MI to 128-bit for AES + if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) + { + LFSR128(state); + // fprintf (stderr, "\n"); + } // fprintf (stderr, " %s", KRED); // fprintf (stderr, "ENC"); } @@ -220,6 +254,27 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180] } } + //reset voice counter at MAC_PTT (inverted, triple check please) + if (state->currentslot == 1 && state->payload_algidR == 0x81) + state->DMRvcL = 0; + + if (state->currentslot == 0 && state->payload_algid == 0x81) + state->DMRvcR = 0; + + //reset voice counter after 2V (AES 256) + if (state->currentslot == 1 && state->payload_algidR == 0x84) + state->DMRvcL = 0; + + if (state->currentslot == 0 && state->payload_algid == 0x84) + state->DMRvcR = 0; + + //reset voice counter after 2V (AES 128) + if (state->currentslot == 1 && state->payload_algidR == 0x89) + state->DMRvcL = 0; + + if (state->currentslot == 0 && state->payload_algid == 0x89) + state->DMRvcR = 0; + fprintf (stderr, "%s", KNRM); } //do not permit MAC_PTT_END with CRC errs, help prevent false positives on calls @@ -538,11 +593,28 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156] if (state->payload_algid != 0x80 && state->payload_algid != 0x0) { fprintf (stderr, "%s", KYEL); - fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid); - fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid); - fprintf (stderr, " MI 0x%016llX", state->payload_miP); - if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R); + fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algid); + fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyid); + fprintf (stderr, " MI: 0x%016llX", state->payload_miP); fprintf(stderr, " MPTT"); + if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R); + if (state->R != 0 && state->payload_algid == 0x81) fprintf (stderr, " Key 0x%016llX", state->R); + + if ( (state->payload_algid == 0x84 || state->payload_algid == 0x89) && state->aes_key_loaded[0] == 1) + { + fprintf (stderr, "\n "); + fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]); + if (state->payload_algid == 0x84) + fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]); + // opts->unmute_encrypted_p25 = 1; //needed? + } + + //expand 64-bit MI to 128-bit for AES + if (state->payload_algid == 0x84 || state->payload_algid == 0x89) + { + LFSR128(state); + // fprintf (stderr, "\n"); + } // fprintf (stderr, " %s", KRED); // fprintf (stderr, "ENC"); } @@ -579,11 +651,28 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156] if (state->payload_algidR != 0x80 && state->payload_algidR != 0x0) { fprintf (stderr, "%s", KYEL); - fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR); - fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR); - fprintf (stderr, " MI 0x%016llX", state->payload_miN); - if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR); + fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algidR); + fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyidR); + fprintf (stderr, " MI: 0x%016llX", state->payload_miN); fprintf(stderr, " MPTT"); + + if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR); + if (state->RR != 0 && state->payload_algidR == 0x81) fprintf (stderr, " Key 0x%016llX", state->RR); + if ( (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) && state->aes_key_loaded[1] == 1) + { + fprintf (stderr, "\n "); + fprintf (stderr, "Key: %016llX %016llX ", state->A1[1], state->A2[1]); + if (state->payload_algidR == 0x84) + fprintf (stderr, "%016llX %016llX", state->A3[1], state->A4[1]); + // opts->unmute_encrypted_p25 = 1; //needed? + } + + //expand 64-bit MI to 128-bit for AES + if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) + { + LFSR128(state); + // fprintf (stderr, "\n"); + } // fprintf (stderr, " %s", KRED); // fprintf (stderr, "ENC"); } @@ -605,6 +694,27 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156] } fprintf (stderr, "%s", KNRM); + //reset voice counter at MAC_PTT + if (state->currentslot == 0 && state->payload_algid == 0x81) + state->DMRvcL = 0; + + if (state->currentslot == 1 && state->payload_algidR == 0x81) + state->DMRvcR = 0; + + //reset voice counter after 2V (AES 256) + if (state->currentslot == 0 && state->payload_algid == 0x84) + state->DMRvcL = 0; + + if (state->currentslot == 1 && state->payload_algidR == 0x84) + state->DMRvcR = 0; + + //reset voice counter after 2V (AES 128) + if (state->currentslot == 0 && state->payload_algid == 0x89) + state->DMRvcL = 0; + + if (state->currentslot == 1 && state->payload_algidR == 0x89) + state->DMRvcR = 0; + } if (opcode == 0x2 && err == 0) {