Congratulations for clicking this link, you are now reading this description;

Add DES-OFB Decryption Support for P25, NXDN, DMR (Tested);

Add DES-XL Decryption Support for P25p1 (Tested);

Add AES-OFB Decryption Support for P25, DMR (Tested); NXDN(untested);

Add P25p1 PDU Decryption Support; (Untested)(Known Modes);

Add Remaining (AES, DES) DMR PDU Decryption Support (Known DMRA Modes)(Untested);

Decrypt Tytera 16-bit BP (works depending on model);

Add AES Keys example csv file for import;

Probably a few bugs that'll need to be massaged out now with all the code additions for several years of stashed code;
This commit is contained in:
lwvmobile
2025-03-14 23:54:58 -04:00
parent 9f59729fb1
commit eac360571e
28 changed files with 3752 additions and 197 deletions

View File

@@ -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
1 keyid(hex), keyvalue(hex)
2 0001,0000000000000000,0000000000000000,0000000000000000,0000002823d87923
3 0003,0101010101010101,0101010101010101
4 0004,0101010101010101,0101010101010101,0101010101010101,0101010101010101
5 C197,A753BC945DE5E0F1,EC1970F8565154E6,D9DF2FAC6278FA93,B531D2CC046E93A2
6 0067,0000000000000000,0000000000000000,0000000000000000,DEADBEEFBAADF00D
7 0000,0000000000000000,0000000000000000,0000000000000000,0000000000000001

View File

@@ -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" {

View File

@@ -1,7 +0,0 @@
/*-------------------------------------------------------------------------------
* 2.c
* Placeholder File 2 -- This file is for temporary code storage
*
*
*
*-----------------------------------------------------------------------------*/

View File

@@ -1,7 +0,0 @@
/*-------------------------------------------------------------------------------
* 4.c
* Placeholder File 4 -- This file is for temporary code storage
*
*
*
*-----------------------------------------------------------------------------*/

View File

@@ -1,7 +0,0 @@
/*-------------------------------------------------------------------------------
* 5.c
* Placeholder File 5 -- This file is for temporary code storage
*
*
*
*-----------------------------------------------------------------------------*/

921
src/crypt-aes.c Normal file
View File

@@ -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 <http://unlicense.org/>
*/
#include <string.h>
#include <stdint.h>
#include <stddef.h>
// #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);
}

831
src/crypt-des.c Normal file
View File

@@ -0,0 +1,831 @@
/*-------------------------------------------------------------------------------
* des.c Crypthings
* DES Alg
*-----------------------------------------------------------------------------*/
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
//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);
}

View File

@@ -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)
{

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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", "");

View File

@@ -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;
}

View File

@@ -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");
}

View File

@@ -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 <dec> 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 <hex> Manually Enter **tera 10/32/64 Char Basic Privacy Hex Key (see example below)\n");
printf (" -H <hex> 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 <hex> 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 <dec> Manually Enter dPMR or NXDN EHR Scrambler Key Value (Decimal Value)\n");
printf (" \n");
printf (" -1 <hex> Manually Enter RC4 Key Value (DMR, P25) (Hex Value) \n");
printf (" -1 <hex> Manually Enter RC4 or DES Key Value (DMR, P25, NXDN) (Hex Value) \n");
printf (" \n");
printf (" -2 <hex> Manually Enter TYT and Enforce 16-bit BP Key Value (DMR) (Hex Value) \n");
printf (" \n");
printf (" -5 <hex> Manually Enter 48-bit BP Key Value (DMR) (Hex Value) \n");
printf (" \n");
printf (" -k <file> 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 <file> 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 <secs> 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')

View File

@@ -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

View File

@@ -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"

View File

@@ -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);
}

View File

@@ -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, " ");

View File

@@ -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'

View File

@@ -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");

View File

@@ -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
{

View File

@@ -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

View File

@@ -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");
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)
{