mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 01:07:24 -05:00
YOLO:
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:
7
examples/example_aes_keys.csv
Normal file
7
examples/example_aes_keys.csv
Normal 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
|
||||
|
@@ -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" {
|
||||
|
||||
7
src/2.c
7
src/2.c
@@ -1,7 +0,0 @@
|
||||
/*-------------------------------------------------------------------------------
|
||||
* 2.c
|
||||
* Placeholder File 2 -- This file is for temporary code storage
|
||||
*
|
||||
*
|
||||
*
|
||||
*-----------------------------------------------------------------------------*/
|
||||
7
src/4.c
7
src/4.c
@@ -1,7 +0,0 @@
|
||||
/*-------------------------------------------------------------------------------
|
||||
* 4.c
|
||||
* Placeholder File 4 -- This file is for temporary code storage
|
||||
*
|
||||
*
|
||||
*
|
||||
*-----------------------------------------------------------------------------*/
|
||||
7
src/5.c
7
src/5.c
@@ -1,7 +0,0 @@
|
||||
/*-------------------------------------------------------------------------------
|
||||
* 5.c
|
||||
* Placeholder File 5 -- This file is for temporary code storage
|
||||
*
|
||||
*
|
||||
*
|
||||
*-----------------------------------------------------------------------------*/
|
||||
921
src/crypt-aes.c
Normal file
921
src/crypt-aes.c
Normal 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
831
src/crypt-des.c
Normal 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);
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
73
src/dmr_le.c
73
src/dmr_le.c
@@ -115,12 +115,23 @@ void dmr_late_entry_mi (dsd_opts * opts, dsd_state * state)
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//run afterwards, or le verification won't match up properly
|
||||
if (state->payload_algid != 0x21)
|
||||
|
||||
//run expansions afterwards, or le verification won't match up properly
|
||||
|
||||
//DES1
|
||||
if (state->payload_algid == 0x22)
|
||||
{
|
||||
LFSR64 (state);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
//AES-128 or AES-256
|
||||
if (state->payload_algid == 0x24 || state->payload_algid == 0x25)
|
||||
{
|
||||
LFSR128d (state);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
}
|
||||
if (slot == 1 && state->payload_algidR != 0)
|
||||
{
|
||||
@@ -134,16 +145,62 @@ void dmr_late_entry_mi (dsd_opts * opts, dsd_state * state)
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//run afterwards, or le verification won't match up properly
|
||||
if (state->payload_algidR != 0x21)
|
||||
|
||||
//run expansions afterwards, or le verification won't match up properly
|
||||
|
||||
//DES1
|
||||
if (state->payload_algidR == 0x22)
|
||||
{
|
||||
LFSR64 (state);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
//AES-128 or AES-256
|
||||
if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25)
|
||||
{
|
||||
LFSR128d (state);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//run LFSR even if golay fails
|
||||
else if (slot == 0 && state->payload_algid != 0)
|
||||
{
|
||||
//DES1
|
||||
if (state->payload_algid == 0x22)
|
||||
{
|
||||
LFSR64 (state);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
//AES-128 or AES-256
|
||||
if (state->payload_algid == 0x24 || state->payload_algid == 0x25)
|
||||
{
|
||||
LFSR128d (state);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
}
|
||||
else if (slot == 1 && state->payload_algidR != 0)
|
||||
{
|
||||
//DES1
|
||||
if (state->payload_algidR == 0x22)
|
||||
{
|
||||
LFSR64 (state);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
//AES-128 or AES-256
|
||||
if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25)
|
||||
{
|
||||
LFSR128d (state);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void dmr_alg_refresh (dsd_opts * opts, dsd_state * state)
|
||||
@@ -195,8 +252,8 @@ void dmr_alg_reset (dsd_opts * opts, dsd_state * state)
|
||||
state->dropR = 256;
|
||||
state->DMRvcL = 0;
|
||||
state->DMRvcR = 0;
|
||||
state->payload_miP = 0;
|
||||
state->payload_miN = 0;
|
||||
// state->payload_miP = 0; //running these clears out before we can create a new keystream
|
||||
// state->payload_miN = 0; //running these clears out before we can create a new keystream
|
||||
}
|
||||
|
||||
//handle Single Burst (Voice Burst F) or Reverse Channel Signalling
|
||||
|
||||
147
src/dmr_pi.c
147
src/dmr_pi.c
@@ -38,15 +38,38 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC
|
||||
//Anytone RC4 Shim
|
||||
if (state->payload_algid == 0x01)
|
||||
{
|
||||
fprintf (stderr, " Anytone (0x01)");
|
||||
fprintf (stderr, " Anytone RC4 (0x01)");
|
||||
state->payload_algid = 0x21;
|
||||
}
|
||||
|
||||
//Anytone/Hytera AES-128 Shim
|
||||
if (state->payload_algid == 0x04)
|
||||
{
|
||||
fprintf (stderr, " Anytone/Hytera AES-128 (0x04)");
|
||||
state->payload_algid = 0x24;
|
||||
}
|
||||
|
||||
//Anytone/Hytera AES-256 Shim
|
||||
if (state->payload_algid == 0x05)
|
||||
{
|
||||
fprintf (stderr, " Anytone/Hytera AES-256 (0x05)");
|
||||
state->payload_algid = 0x25;
|
||||
}
|
||||
|
||||
fprintf (stderr, "%s ", KNRM);
|
||||
if (state->payload_algid != 0x21)
|
||||
|
||||
//expand the 32-bit MI to a 64-bit DES1 IV
|
||||
if (state->payload_algid == 0x22)
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
LFSR64 (state);
|
||||
}
|
||||
|
||||
//expand the 32-bit MI to a 128-bit AES IV
|
||||
if (state->payload_algid == 0x24 || state->payload_algid == 0x25)
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
LFSR128d (state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,11 +100,34 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC
|
||||
state->payload_algidR = 0x21;
|
||||
}
|
||||
|
||||
//Anytone/Hytera AES-128 Shim
|
||||
if (state->payload_algidR == 0x04)
|
||||
{
|
||||
fprintf (stderr, " Anytone/Hytera AES-128 (0x04)");
|
||||
state->payload_algidR = 0x24;
|
||||
}
|
||||
|
||||
//Anytone/Hytera AES-256 Shim
|
||||
if (state->payload_algidR == 0x05)
|
||||
{
|
||||
fprintf (stderr, " Anytone/Hytera AES-256 (0x05)");
|
||||
state->payload_algidR = 0x25;
|
||||
}
|
||||
|
||||
fprintf (stderr, "%s ", KNRM);
|
||||
if (state->payload_algidR != 0x21)
|
||||
|
||||
//expand the 32-bit MI to a 64-bit DES1 IV
|
||||
if (state->payload_algidR == 0x22)
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
LFSR64 (state);
|
||||
}
|
||||
|
||||
//expand the 32-bit MI to a 128-bit AES IV
|
||||
if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25)
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
LFSR128d (state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +166,7 @@ void LFSR(dsd_state * state)
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Slot 1");
|
||||
fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algid, state->payload_keyid);
|
||||
fprintf(stderr, " MI: 0x%08X", lfsr);
|
||||
fprintf(stderr, " MI(32): 0x%08X", lfsr);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
state->payload_mi = lfsr;
|
||||
}
|
||||
@@ -131,12 +177,13 @@ void LFSR(dsd_state * state)
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Slot 2");
|
||||
fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algidR, state->payload_keyidR);
|
||||
fprintf(stderr, " MI: 0x%08X", lfsr);
|
||||
fprintf(stderr, " MI(32): 0x%08X", lfsr);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
state->payload_miR = lfsr;
|
||||
}
|
||||
}
|
||||
|
||||
//Expand a 32-bit MI into a 64-bit IV for DES
|
||||
void LFSR64(dsd_state * state)
|
||||
{
|
||||
{
|
||||
@@ -161,9 +208,11 @@ void LFSR64(dsd_state * state)
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Slot 1");
|
||||
fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algid, state->payload_keyid);
|
||||
fprintf (stderr, " MI: 0x%016llX", lfsr);
|
||||
fprintf (stderr, " MI(64): 0x%016llX", lfsr);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
state->payload_mi = lfsr & 0xFFFFFFFF; //truncate for next repitition and le verification
|
||||
state->payload_miP = lfsr;
|
||||
state->DMRvcL = 0;
|
||||
}
|
||||
|
||||
if (state->currentslot == 1)
|
||||
@@ -171,10 +220,94 @@ void LFSR64(dsd_state * state)
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Slot 2");
|
||||
fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X", state->payload_algidR, state->payload_keyidR);
|
||||
fprintf (stderr, " MI: 0x%016llX", lfsr);
|
||||
fprintf (stderr, " MI(64): 0x%016llX", lfsr);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
state->payload_miR = lfsr & 0xFFFFFFFF; //truncate for next repitition and le verification
|
||||
state->payload_miN = lfsr;
|
||||
state->DMRvcR = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Expand a 32-bit MI into a 128-bit IV for AES
|
||||
void LFSR128d(dsd_state * state)
|
||||
{
|
||||
unsigned long long int lfsr = 0;
|
||||
|
||||
if (state->currentslot == 0)
|
||||
lfsr = state->payload_mi;
|
||||
else lfsr = state->payload_miR;
|
||||
|
||||
unsigned long long int next_mi;
|
||||
|
||||
//start packing aes_iv
|
||||
if (state->currentslot == 0)
|
||||
{
|
||||
state->aes_iv[0] = (lfsr >> 24) & 0xFF;
|
||||
state->aes_iv[1] = (lfsr >> 16) & 0xFF;
|
||||
state->aes_iv[2] = (lfsr >> 8 ) & 0xFF;
|
||||
state->aes_iv[3] = (lfsr >> 0 ) & 0xFF;
|
||||
}
|
||||
else if (state->currentslot == 1)
|
||||
{
|
||||
state->aes_ivR[0] = (lfsr >> 24) & 0xFF;
|
||||
state->aes_ivR[1] = (lfsr >> 16) & 0xFF;
|
||||
state->aes_ivR[2] = (lfsr >> 8 ) & 0xFF;
|
||||
state->aes_ivR[3] = (lfsr >> 0 ) & 0xFF;
|
||||
}
|
||||
|
||||
int cnt = 0; int x = 32;
|
||||
unsigned long long int bit;
|
||||
for(cnt=0;cnt<96;cnt++)
|
||||
{
|
||||
//32,22,2,1
|
||||
bit = ( (lfsr >> 31) ^ (lfsr >> 21) ^ (lfsr >> 1) ^ (lfsr >> 0) ) & 0x1;
|
||||
lfsr = (lfsr << 1) | bit;
|
||||
|
||||
//continue packing aes_iv
|
||||
if (state->currentslot == 0)
|
||||
state->aes_iv[x/8] = (state->aes_iv[x/8] << 1) + bit;
|
||||
else if (state->currentslot == 1)
|
||||
state->aes_ivR[x/8] = (state->aes_ivR[x/8] << 1) + bit;
|
||||
x++;
|
||||
}
|
||||
|
||||
//assign the next 32-bit short MI from 4,5,6,7 so it'll match up with OTA late entry
|
||||
if (state->currentslot == 0)
|
||||
next_mi = (state->aes_iv[4] << 24) + (state->aes_iv[5] << 16) + (state->aes_iv[6] << 8) + (state->aes_iv[7] << 0);
|
||||
if (state->currentslot == 1)
|
||||
next_mi = (state->aes_ivR[4] << 24) + (state->aes_ivR[5] << 16) + (state->aes_ivR[6] << 8) + (state->aes_ivR[7] << 0);
|
||||
|
||||
if (state->currentslot == 0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Slot 1");
|
||||
fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X MI(128): ", state->payload_algid, state->payload_keyid);
|
||||
for (x = 0; x < 16; x++)
|
||||
fprintf (stderr, "%02X", state->aes_iv[x]);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
// fprintf (stderr, "\n");
|
||||
|
||||
state->payload_mi = next_mi;
|
||||
state->DMRvcL = 0;
|
||||
|
||||
}
|
||||
|
||||
if (state->currentslot == 1)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Slot 2");
|
||||
fprintf (stderr, " DMR PI C- ALG ID: 0x%02X KEY ID: 0x%02X MI(128): ", state->payload_algidR, state->payload_keyidR);
|
||||
for (x = 0; x < 16; x++)
|
||||
fprintf (stderr, "%02X", state->aes_ivR[x]);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
// fprintf (stderr, "\n");
|
||||
|
||||
state->payload_miR = next_mi;
|
||||
state->DMRvcR = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
162
src/dsd_audio2.c
162
src/dsd_audio2.c
@@ -93,13 +93,21 @@ void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state)
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x21)
|
||||
else if (state->payload_algid == 0x21 || state->payload_algid == 0x22)
|
||||
{
|
||||
if (state->R != 0)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x24 || state->payload_algid == 0x25)
|
||||
{
|
||||
//going to need a better check for this later on, or seperated keys or something
|
||||
if (state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (encR)
|
||||
@@ -111,15 +119,27 @@ void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state)
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algidR == 0x21)
|
||||
else if (state->payload_algidR == 0x21 || state->payload_algidR == 0x22)
|
||||
{
|
||||
if (state->RR != 0)
|
||||
{
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25)
|
||||
{
|
||||
//going to need a better check for this later on, or seperated keys or something
|
||||
if (state->aes_key_loaded[1] == 1)
|
||||
{
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//debug disable enc check for AES testing
|
||||
// encL = 0;
|
||||
// encR = 0;
|
||||
|
||||
//TODO: add option to bypass enc with a toggle as well
|
||||
|
||||
//CHEAT: Using the slot on/off, use that to set encL or encR back on
|
||||
@@ -312,6 +332,20 @@ void playSynthesizedVoiceFS4 (dsd_opts * opts, dsd_state * state)
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x81)
|
||||
{
|
||||
if (state->R != 0)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x84 || state->payload_algid == 0x89)
|
||||
{
|
||||
if (state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (encR)
|
||||
@@ -323,6 +357,20 @@ void playSynthesizedVoiceFS4 (dsd_opts * opts, dsd_state * state)
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algidR == 0x81)
|
||||
{
|
||||
if (state->R != 0)
|
||||
{
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89)
|
||||
{
|
||||
if (state->aes_key_loaded[1] == 1)
|
||||
{
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//CHEAT: Using the slot on/off, use that to set encL or encR back on
|
||||
@@ -520,13 +568,20 @@ void playSynthesizedVoiceFS (dsd_opts * opts, dsd_state * state)
|
||||
//checkdown to see if we can lift the 'mute' if a key is available
|
||||
if (encL)
|
||||
{
|
||||
if (state->payload_algid == 0xAA)
|
||||
if (state->payload_algid == 0xAA || state->payload_algid == 0x81 || state->payload_algid == 0x9F)
|
||||
{
|
||||
if (state->R != 0)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x84 || state->payload_algid == 0x89 || state->payload_algid == 0x83)
|
||||
{
|
||||
if (state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: add option to bypass enc with a toggle as well
|
||||
@@ -654,13 +709,20 @@ void playSynthesizedVoiceFM (dsd_opts * opts, dsd_state * state)
|
||||
//checkdown to see if we can lift the 'mute' if a key is available
|
||||
if (encL)
|
||||
{
|
||||
if (state->payload_algid == 0xAA || state->nxdn_cipher_type == 0x1)
|
||||
if (state->payload_algid == 0xAA || state->payload_algid == 0x81 || state->payload_algid == 0x83 || state->payload_algid == 0x9F || state->nxdn_cipher_type == 0x1 || state->nxdn_cipher_type == 0x2)
|
||||
{
|
||||
if (state->R != 0)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x84 || state->payload_algid == 0x89 || state->nxdn_cipher_type == 0x3)
|
||||
{
|
||||
if (state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//WIP: Mute if on B list (or not W list)
|
||||
@@ -870,13 +932,20 @@ void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state)
|
||||
//checkdown to see if we can lift the 'mute' if a key is available
|
||||
if (encL)
|
||||
{
|
||||
if (state->payload_algid == 0xAA)
|
||||
if (state->payload_algid == 0xAA || state->payload_algid == 0x81 || state->payload_algid == 0x9F || state->payload_algid == 0x83)
|
||||
{
|
||||
if (state->R != 0)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x84 || state->payload_algid == 0x89)
|
||||
{
|
||||
if (state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//TODO: add option to bypass enc with a toggle as well
|
||||
|
||||
@@ -993,7 +1062,7 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
|
||||
encL = (state->dmr_so >> 6) & 0x1;
|
||||
encR = (state->dmr_soR >> 6) & 0x1;
|
||||
|
||||
//checkdown to see if we can lift the 'mute' if a key is available
|
||||
//checkdown to see if we can lift the 'mute' if a key is available
|
||||
if (encL)
|
||||
{
|
||||
if (state->payload_algid == 0)
|
||||
@@ -1003,13 +1072,21 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x21)
|
||||
else if (state->payload_algid == 0x21 || state->payload_algid == 0x22)
|
||||
{
|
||||
if (state->R != 0)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x24 || state->payload_algid == 0x25)
|
||||
{
|
||||
//going to need a better check for this later on, or seperated keys or something
|
||||
if (state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (encR)
|
||||
@@ -1021,15 +1098,26 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algidR == 0x21)
|
||||
else if (state->payload_algidR == 0x21 || state->payload_algidR == 0x22)
|
||||
{
|
||||
if (state->RR != 0)
|
||||
{
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algidR == 0x24 || state->payload_algidR == 0x25)
|
||||
{
|
||||
//going to need a better check for this later on, or seperated keys or something
|
||||
if (state->aes_key_loaded[1] == 1)
|
||||
{
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//debug for AES
|
||||
// encL = encR = 0;
|
||||
|
||||
//TODO: add option to bypass enc with a toggle as well
|
||||
|
||||
//CHEAT: Using the slot on/off, use that to set encL or encR back on
|
||||
@@ -1342,6 +1430,20 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state)
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x81)
|
||||
{
|
||||
if (state->R != 0)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algid == 0x84 || state->payload_algid == 0x89)
|
||||
{
|
||||
if (state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (encR)
|
||||
@@ -1353,6 +1455,20 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state)
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algidR == 0x81)
|
||||
{
|
||||
if (state->R != 0)
|
||||
{
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
else if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89)
|
||||
{
|
||||
if (state->aes_key_loaded[1] == 1)
|
||||
{
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1552,26 +1668,52 @@ void playSynthesizedVoiceSS18 (dsd_opts * opts, dsd_state * state)
|
||||
//checkdown to see if we can lift the 'mute' if a key is available
|
||||
if (encL)
|
||||
{
|
||||
if (state->payload_algid == 0xAA)
|
||||
//RC4 or DES
|
||||
if (state->payload_algid == 0xAA || state->payload_algid == 0x81)
|
||||
{
|
||||
if (state->R != 0)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//AES
|
||||
if (state->payload_algid == 0x84 || state->payload_algid == 0x89)
|
||||
{
|
||||
if (state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
encL = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (encR)
|
||||
{
|
||||
if (state->payload_algidR == 0xAA)
|
||||
//RC4 or DES
|
||||
if (state->payload_algidR == 0xAA || state->payload_algidR == 0x81)
|
||||
{
|
||||
if (state->RR != 0)
|
||||
{
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//AES
|
||||
if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89)
|
||||
{
|
||||
if (state->aes_key_loaded[1] == 1)
|
||||
{
|
||||
encR = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//debug, unmute both slots
|
||||
// encL = 0;
|
||||
// encR = 0;
|
||||
|
||||
//WIP: Mute if on B list (or not W list)
|
||||
char modeL[8];
|
||||
sprintf (modeL, "%s", "");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
|
||||
114
src/dsd_main.c
114
src/dsd_main.c
@@ -347,6 +347,21 @@ noCarrier (dsd_opts * opts, dsd_state * state)
|
||||
state->p25vc = 0;
|
||||
state->payload_miP = 0;
|
||||
|
||||
//ks array storage and counters
|
||||
memset (state->ks_octetL, 0, sizeof(state->ks_octetL));
|
||||
memset (state->ks_octetR, 0, sizeof(state->ks_octetR));
|
||||
memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL));
|
||||
memset (state->ks_bitstreamR, 0, sizeof(state->ks_bitstreamR));
|
||||
state->octet_counter = 0;
|
||||
state->bit_counterL = 0;
|
||||
state->bit_counterR = 0;
|
||||
|
||||
//xl specific, we need to know if the ESS is from HDU, or from LDU2
|
||||
state->xl_is_hdu = 0;
|
||||
|
||||
//NXDN, when a new IV has arrived
|
||||
state->nxdn_new_iv = 0;
|
||||
|
||||
//initialize dmr data header source
|
||||
state->dmr_lrrp_source[0] = 0;
|
||||
state->dmr_lrrp_source[1] = 0;
|
||||
@@ -412,7 +427,15 @@ noCarrier (dsd_opts * opts, dsd_state * state)
|
||||
state->R = 0; //NXDN, or RC4 (slot 1)
|
||||
state->RR = 0; //RC4 (slot 2)
|
||||
state->K = 0; //BP
|
||||
state->K1 = 0; //tera 10 char BP
|
||||
state->K1 = 0; //tera 10/32/64 char BP
|
||||
state->K2 = 0;
|
||||
state->K3 = 0;
|
||||
state->K4 = 0;
|
||||
memset (state->A1, 0, sizeof(state->A1));
|
||||
memset (state->A2, 0, sizeof(state->A2));
|
||||
memset (state->A3, 0, sizeof(state->A3));
|
||||
memset (state->A4, 0, sizeof(state->A4));
|
||||
memset (state->aes_key_loaded, 0, sizeof (state->aes_key_loaded));
|
||||
state->H = 0; //shim for above
|
||||
}
|
||||
|
||||
@@ -1020,9 +1043,34 @@ initState (dsd_state * state)
|
||||
state->dropL = 256;
|
||||
state->dropR = 256;
|
||||
|
||||
state->p25vc = 0;
|
||||
//ks array storage and counters
|
||||
memset (state->ks_octetL, 0, sizeof(state->ks_octetL));
|
||||
memset (state->ks_octetR, 0, sizeof(state->ks_octetR));
|
||||
memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL));
|
||||
memset (state->ks_bitstreamR, 0, sizeof(state->ks_bitstreamR));
|
||||
state->octet_counter = 0;
|
||||
state->bit_counterL = 0;
|
||||
state->bit_counterR = 0;
|
||||
|
||||
//AES Specific Variables
|
||||
memset (state->aes_key, 0, sizeof(state->aes_key));
|
||||
memset (state->aes_iv, 0, sizeof(state->aes_iv));
|
||||
memset (state->aes_ivR, 0, sizeof(state->aes_ivR));
|
||||
memset (state->A1, 0, sizeof(state->A1));
|
||||
memset (state->A2, 0, sizeof(state->A2));
|
||||
memset (state->A3, 0, sizeof(state->A3));
|
||||
memset (state->A4, 0, sizeof(state->A4));
|
||||
memset (state->aes_key_loaded, 0, sizeof (state->aes_key_loaded));
|
||||
|
||||
//xl specific, we need to know if the ESS is from HDU, or from LDU2
|
||||
state->xl_is_hdu = 0;
|
||||
|
||||
//NXDN, when a new IV has arrived
|
||||
state->nxdn_new_iv = 0;
|
||||
|
||||
state->p25vc = 0;
|
||||
state->payload_miP = 0;
|
||||
state->payload_miN = 0;
|
||||
|
||||
//initialize dmr data header source
|
||||
state->dmr_lrrp_source[0] = 0;
|
||||
@@ -1453,24 +1501,33 @@ usage ()
|
||||
printf (" -b <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')
|
||||
|
||||
540
src/dsd_mbe.c
540
src/dsd_mbe.c
@@ -29,41 +29,33 @@ void keyring(dsd_opts * opts, dsd_state * state)
|
||||
|
||||
if (state->currentslot == 1)
|
||||
state->RR = state->rkey_array[state->payload_keyidR];
|
||||
}
|
||||
|
||||
void RC4(int drop, uint8_t keylength, uint8_t messagelength, uint8_t key[], uint8_t cipher[], uint8_t plain[])
|
||||
{
|
||||
int i, j, count;
|
||||
uint8_t t, b;
|
||||
|
||||
//init Sbox
|
||||
uint8_t S[256];
|
||||
for(int i = 0; i < 256; i++) S[i] = i;
|
||||
|
||||
//Key Scheduling
|
||||
j = 0;
|
||||
for(i = 0; i < 256; i++)
|
||||
//load any large keys (AES)
|
||||
if (state->currentslot == 0)
|
||||
{
|
||||
j = (j + S[i] + key[i % keylength]) % 256;
|
||||
t = S[i];
|
||||
S[i] = S[j];
|
||||
S[j] = t;
|
||||
state->A1[0] = state->rkey_array[state->payload_keyid+0x000];
|
||||
state->A2[0] = state->rkey_array[state->payload_keyid+0x101];
|
||||
state->A3[0] = state->rkey_array[state->payload_keyid+0x201];
|
||||
state->A4[0] = state->rkey_array[state->payload_keyid+0x301];
|
||||
|
||||
//check to see if there is a value loaded or not
|
||||
if (state->A1[0] == 0 && state->A2[0] == 0 && state->A3[0] == 0 && state->A4[0] == 0)
|
||||
state->aes_key_loaded[0] = 0;
|
||||
else state->aes_key_loaded[0] = 1;
|
||||
|
||||
}
|
||||
|
||||
//Drop Bytes and Cipher Byte XOR
|
||||
i = j = 0;
|
||||
for(count = 0; count < (messagelength + drop); count++)
|
||||
if (state->currentslot == 1)
|
||||
{
|
||||
i = (i + 1) % 256;
|
||||
j = (j + S[i]) % 256;
|
||||
t = S[i];
|
||||
S[i] = S[j];
|
||||
S[j] = t;
|
||||
b = S[(S[i] + S[j]) % 256];
|
||||
state->A1[1] = state->rkey_array[state->payload_keyidR+0x000];
|
||||
state->A2[1] = state->rkey_array[state->payload_keyidR+0x101];
|
||||
state->A3[1] = state->rkey_array[state->payload_keyidR+0x201];
|
||||
state->A4[1] = state->rkey_array[state->payload_keyidR+0x301];
|
||||
|
||||
//return mbe payload byte here
|
||||
if (count >= drop)
|
||||
plain[count - drop] = b^cipher[count - drop];
|
||||
//check to see if there is a value loaded or not
|
||||
if (state->A1[1] == 0 && state->A2[1] == 0 && state->A3[1] == 0 && state->A4[1] == 0)
|
||||
state->aes_key_loaded[1] = 0;
|
||||
else state->aes_key_loaded[1] = 1;
|
||||
|
||||
}
|
||||
|
||||
@@ -261,6 +253,90 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
mbe_demodulateImbe7200x4400Data (imbe_fr);
|
||||
state->errs2 += mbe_eccImbe7200x4400Data (imbe_fr, imbe_d);
|
||||
|
||||
//P25p1 Multi Crypt Handler (DES1, DES3, DES-XL and AES)
|
||||
if ( (state->payload_algid == 0x81 && state->R != 0) || //DES-56
|
||||
(state->payload_algid == 0x9F && state->R != 0) || //DES-XL
|
||||
(state->payload_algid == 0x84 && state->aes_key_loaded[0] == 1) ||
|
||||
(state->payload_algid == 0x89 && state->aes_key_loaded[0] == 1) ||
|
||||
(state->payload_algid == 0x83 && state->aes_key_loaded[0] == 1) ) //3DES
|
||||
{
|
||||
uint8_t cipher[11];
|
||||
uint8_t plain[11];
|
||||
memset (cipher, 0, sizeof(cipher));
|
||||
memset (plain, 0, sizeof(plain));
|
||||
|
||||
uint8_t aes_key[32];
|
||||
memset (aes_key, 0, sizeof(aes_key));
|
||||
|
||||
//Load key from A1 - A4
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
aes_key[i+0] = (state->A1[0] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+8] = (state->A2[0] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+16] = (state->A3[0] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+24] = (state->A4[0] >> (56-(i*8))) & 0xFF;
|
||||
}
|
||||
|
||||
if (state->p25vc == 0)
|
||||
{
|
||||
if (state->payload_algid == 0x81 || state->payload_algid == 0x83) //DES1 and DES3
|
||||
state->octet_counter = 11+8; //start on 19 for DES-OFB (8 discard + 8 LC + 3 reserved)
|
||||
else if (state->payload_algid == 0x9F)
|
||||
state->octet_counter = 11; //11 with info from LFSR run values (no discard)
|
||||
else
|
||||
state->octet_counter = 11+16; //start on 27 for AES (16 discard + 8 LC + 3 reserved)
|
||||
memset (state->ks_octetL, 0, sizeof(state->ks_octetL));
|
||||
|
||||
//debug
|
||||
// fprintf (stderr, "\n KO: %d; ", state->octet_counter);
|
||||
|
||||
if (state->payload_algid == 0x81) //DES-56
|
||||
des_multi_keystream_output (state->payload_miP, state->R, state->ks_octetL, 1, 28);
|
||||
if (state->payload_algid == 0x83) //3DES, or TDEA
|
||||
tdea_multi_keystream_output (state->payload_miP, aes_key, state->ks_octetL, 1, 28);
|
||||
if (state->payload_algid == 0x9F) //DES-XL
|
||||
des_multi_keystream_output (state->payload_miP, state->R, state->ks_octetL, 2, state->xl_is_hdu); //hard coded bit count value, xl_is_hdu determines lfsr run values
|
||||
if (state->payload_algid == 0x84) //AES256
|
||||
aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 2, 14); //14 + 1 discard round
|
||||
if (state->payload_algid == 0x89) //AES128
|
||||
aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 0, 14); //14 + 1 discard round
|
||||
|
||||
}
|
||||
|
||||
int z = 0; int j = 0;
|
||||
for (i = 0; i < 11; i++)
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
cipher[i] = cipher[i] << 1;
|
||||
cipher[i] = cipher[i] + imbe_d[z];
|
||||
imbe_d[z] = 0;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
|
||||
//debug output blocks
|
||||
// fprintf (stderr, "\n OB:");
|
||||
for (i = 0; i < 11; i++)
|
||||
{
|
||||
// fprintf (stderr, " %02X", state->ks_octetL[state->octet_counter]);
|
||||
plain[i] = cipher[i] ^ state->ks_octetL[state->octet_counter++];
|
||||
}
|
||||
|
||||
z = 0;
|
||||
for (i = 0; i < 11; i++)
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
imbe_d[z] = (plain[i] & 0x80) >> 7;
|
||||
plain[i] = plain[i] << 1;
|
||||
z++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//P25p1 RC4 Handling
|
||||
if (state->payload_algid == 0xAA && state->R != 0)
|
||||
{
|
||||
@@ -313,7 +389,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
}
|
||||
}
|
||||
|
||||
RC4(state->dropL, 13, 11, rckey, cipher, plain);
|
||||
rc4_voice_decrypt(state->dropL, 13, 11, rckey, cipher, plain);
|
||||
state->dropL += 11;
|
||||
|
||||
z = 0;
|
||||
@@ -357,6 +433,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
if (opts->payload == 1)
|
||||
{
|
||||
PrintIMBEData (opts, state, imbe_d);
|
||||
fprintf (stderr, " 7100");
|
||||
}
|
||||
|
||||
mbe_convertImbe7100to7200(imbe_d);
|
||||
@@ -388,7 +465,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
||||
state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
||||
|
||||
if ( (state->nxdn_cipher_type == 0x01 && state->R > 0) ||
|
||||
if ( (state->nxdn_cipher_type == 0x01 && state->R != 0) ||
|
||||
(state->M == 1 && state->R > 0) )
|
||||
{
|
||||
|
||||
@@ -407,6 +484,68 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
|
||||
}
|
||||
|
||||
//NXDN Generic Cipher 2 and Cipher 3 Keystream Application (to be tested)
|
||||
else if ( (state->nxdn_cipher_type == 0x02 && state->R != 0) ||
|
||||
(state->nxdn_cipher_type == 0x03 && state->aes_key_loaded[0] == 1) )
|
||||
{
|
||||
|
||||
if (state->nxdn_cipher_type == 0x02 && state->nxdn_new_iv == 1 && state->nxdn_part_of_frame == 0)
|
||||
{
|
||||
|
||||
//more debug
|
||||
// fprintf (stderr, " IV: %016llX; Key: %016llX", state->payload_miN, state->R);
|
||||
|
||||
memset (state->ks_octetL, 0, sizeof(state->ks_octetL));
|
||||
memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL));
|
||||
|
||||
des_multi_keystream_output (state->payload_miN, state->R, state->ks_octetL, 1, 26); //32 4V at 49 bits = 1568/64 = 24.5 + 1 discard block
|
||||
|
||||
//reset bit_counter
|
||||
state->bit_counterL = 0;
|
||||
|
||||
//unpack the octets into a bit-wise keystream
|
||||
unpack_byte_array_into_bit_array(state->ks_octetL+8, state->ks_bitstreamL, 26*8);
|
||||
|
||||
//reset flag to 0
|
||||
state->nxdn_new_iv = 0;
|
||||
|
||||
}
|
||||
|
||||
//untested, but same setup as DES, so it 'SHOULD' work...maybe
|
||||
if (state->nxdn_cipher_type == 0x03 && state->nxdn_new_iv == 1 && state->nxdn_part_of_frame == 0)
|
||||
{
|
||||
|
||||
//more debug
|
||||
fprintf (stderr, " IV: %016llX; Key: %016llX", state->payload_miN, state->R);
|
||||
|
||||
memset (state->ks_octetL, 0, sizeof(state->ks_octetL));
|
||||
memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL));
|
||||
|
||||
aes_ofb_keystream_output (state->aes_ivR, state->aes_key, state->ks_octetL, 2, 15); //14 + 1 discard round
|
||||
|
||||
//reset bit_counter
|
||||
state->bit_counterL = 0;
|
||||
|
||||
//unpack the octets into a bit-wise keystream
|
||||
unpack_byte_array_into_bit_array(state->ks_octetL+8, state->ks_bitstreamL, 15*8);
|
||||
|
||||
//reset flag to 0
|
||||
state->nxdn_new_iv = 0;
|
||||
|
||||
}
|
||||
|
||||
//sanity check, don't exceed bit application counter
|
||||
if (state->bit_counterL > (1568-49))
|
||||
state->bit_counterL = (1568-49);
|
||||
|
||||
//Keystream creation is currently inside of the NXDN_decode_VCALL_IV function
|
||||
for (i = 0; i < 49; i++)
|
||||
ambe_d[i] ^= state->ks_bitstreamL[state->bit_counterL++];
|
||||
|
||||
// fprintf (stderr, " bc: %04d;", state->bit_counterL); //debug to see what the counter value is up to currently (seems nominal)
|
||||
|
||||
}
|
||||
|
||||
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
||||
ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
||||
|
||||
@@ -432,6 +571,53 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
||||
state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
||||
|
||||
//TYT (Tytera) 16-bit Key (Shuffle/Shift/Inversion Method)
|
||||
if (state->M == 0x16)
|
||||
{
|
||||
//insert an expansion function here
|
||||
unsigned long long int k = 0;
|
||||
uint8_t pNT[56]; memset (pNT, 0, sizeof(pNT));
|
||||
|
||||
//I believe I have this one figured out now
|
||||
//its just a shuffle, shift, invert, shift, invert, shift pattern
|
||||
//could be an lfsr attached, but couldn't figure out the taps
|
||||
|
||||
//below is the pattern found for the 16-bit keys listed on the right
|
||||
// k = 0xFFFF00FFFF00; // 0xFFFF
|
||||
// k = 0x3412CB1234ED; // 0x1234
|
||||
|
||||
//shuffle, invert, shift...and organize into proper key value
|
||||
k = ((state->H & 0xFF) << 8) + ((state->H & 0xFF00) >> 8);
|
||||
k = k << 8 | ((~(state->H & 0xFF) >> 0) & 0xFF);
|
||||
k = k << 16 | state->H;
|
||||
k = k << 8 | ((~(state->H & 0xFF00) >> 8) & 0xFF);
|
||||
|
||||
//debug -- print 48-bit expanded key value
|
||||
// fprintf (stderr, "K: %012llX", k);
|
||||
|
||||
for (int j = 0; j < 48; j++)
|
||||
{
|
||||
x = ( ((k << j) & 0x800000000000) >> 47 ) & 1;
|
||||
ambe_d[j] ^= x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Forced 48-bit Keystream Application "Quick and Dirty" XOR
|
||||
if (state->M == 0x48)
|
||||
{
|
||||
// k = 0xD991633EC82E; //F811A5B94C2D ⊻ 2180C6878403 (1234 EP Key)
|
||||
// k = 0x7F5363362BBE; //F811A5B94C2D ⊻ 8742C68F6793 (AAAA EP Key)
|
||||
// k = 0x409231C77C08; (FFFF EP Key)
|
||||
k = state->H;
|
||||
for (int j = 0; j < 48; j++) //49
|
||||
{
|
||||
x = ( ((k << j) & 0x800000000000) >> 47 );
|
||||
ambe_d[j] ^= x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//EXPERIMENTAL!!
|
||||
//load basic privacy key number from array by the tg value (if not forced)
|
||||
//currently only Moto BP and Hytera 10 Char BP
|
||||
@@ -535,6 +721,125 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
state->DMRvcL++;
|
||||
}
|
||||
|
||||
//DMR and P25p2 DES-OFB 56 Handling, Slot 1, VCH 0 -- consider moving into the AES handler
|
||||
if ( (state->currentslot == 0 && state->payload_algid == 0x22 && state->R != 0) ||
|
||||
(state->currentslot == 0 && state->payload_algid == 0x81 && state->R != 0) )
|
||||
{
|
||||
|
||||
//sanity check in case of error
|
||||
if (state->DMRvcL > 17) state->DMRvcL = 17;
|
||||
|
||||
int j; int z = 0; int n = 8; uint8_t b = 0;
|
||||
if (state->DMRvcL == 0)
|
||||
{
|
||||
memset (state->ks_octetL, 0, sizeof(state->ks_octetL));
|
||||
memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL));
|
||||
state->bit_counterL = 0;
|
||||
|
||||
//check all these comments I'm making for accuracy
|
||||
des_multi_keystream_output (state->payload_miP, state->R, state->ks_octetL, 1, 19); //18 + 1
|
||||
|
||||
//Load Keystream Octet Bytes directly into a bit array, that way we don't have
|
||||
//to keep track of the byte positions and masks for the 49th bit
|
||||
for (i = 0; i < 18 * 8; i++) //19 blocks minus 1 discard block at 8 bits each
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
b = (( (state->ks_octetL[n] << j) & 0x80) >> 7);
|
||||
state->ks_bitstreamL[z++] = b;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
//now we do the bit by bit xor depending on the frame and position of the state bit counter
|
||||
//run 6 instead of 7 so we can just do bit 49 outside of loop to keep extra bits overloading the array
|
||||
z = 0;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
ambe_d[z++] ^= state->ks_bitstreamL[state->bit_counterL++];
|
||||
}
|
||||
|
||||
//last bit
|
||||
ambe_d[48] ^= state->ks_bitstreamL[state->bit_counterL++];
|
||||
|
||||
//skip the next 7 bits of the array
|
||||
state->bit_counterL += 7;
|
||||
|
||||
//increment vc counter by one
|
||||
state->DMRvcL++;
|
||||
|
||||
}
|
||||
|
||||
//DMR and P25p2 AES 256, Slot 1, VCH 0 -- need a way to make sure we have a key when zero fill on some parts of it //&& state->aes_key_loaded[0] == 1
|
||||
if ( (state->currentslot == 0 && state->payload_algid == 0x24 && state->aes_key_loaded[0] == 1 ) || //DMR AES128
|
||||
(state->currentslot == 0 && state->payload_algid == 0x25 && state->aes_key_loaded[0] == 1 ) || //DMR AES256
|
||||
(state->currentslot == 0 && state->payload_algid == 0x89 && state->aes_key_loaded[0] == 1 ) || //P25 AES128
|
||||
(state->currentslot == 0 && state->payload_algid == 0x84 && state->aes_key_loaded[0] == 1) ) //P25 AES256
|
||||
{
|
||||
|
||||
int j; int z = 0; int n = 16; uint8_t b = 0; //n=16 for AES-OFB discard round
|
||||
uint8_t aes_key[32];
|
||||
memset (aes_key, 0, sizeof(aes_key));
|
||||
|
||||
//Load key from A1 - A4
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
aes_key[i+0] = (state->A1[0] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+8] = (state->A2[0] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+16] = (state->A3[0] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+24] = (state->A4[0] >> (56-(i*8))) & 0xFF;
|
||||
}
|
||||
|
||||
//sanity check in case of error
|
||||
if (state->DMRvcL > 17) state->DMRvcL = 17;
|
||||
|
||||
if (state->DMRvcL == 0)
|
||||
{
|
||||
memset (state->ks_octetL, 0, sizeof(state->ks_octetL));
|
||||
memset (state->ks_bitstreamL, 0, sizeof(state->ks_bitstreamL));
|
||||
state->bit_counterL = 0;
|
||||
|
||||
if(state->payload_algid == 0x24 || state->payload_algid == 0x89) //AES128
|
||||
aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 0, 10); //9 + 1 discard round
|
||||
if(state->payload_algid == 0x25 || state->payload_algid == 0x84) //AES256
|
||||
aes_ofb_keystream_output (state->aes_iv, aes_key, state->ks_octetL, 2, 10); //9 + 1 discard round
|
||||
|
||||
//Load Keystream Octet Bytes directly into keystream array
|
||||
for (i = 0; i < 9 * 16; i++) //9 rounds at 16 octets
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
b = (( (state->ks_octetL[n] << j) & 0x80) >> 7);
|
||||
state->ks_bitstreamL[z++] = b;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
//now we do the bit by bit xor depending on the frame and position of the state bit counter
|
||||
//run 6 instead of 7 so we can just do bit 49 outside of loop to keep extra bits overloading the array
|
||||
z = 0;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
ambe_d[z++] ^= state->ks_bitstreamL[state->bit_counterL++];
|
||||
}
|
||||
|
||||
//last bit
|
||||
ambe_d[48] ^= state->ks_bitstreamL[state->bit_counterL++];
|
||||
|
||||
//skip the next 7 bits of the array
|
||||
state->bit_counterL += 7;
|
||||
|
||||
//increment vc counter by one
|
||||
state->DMRvcL++;
|
||||
|
||||
opts->dmr_mute_encL = 0; //shim to unmute
|
||||
|
||||
}
|
||||
|
||||
//DMR RC4, Slot 1
|
||||
if (state->currentslot == 0 && state->payload_algid == 0x21 && state->R != 0)
|
||||
{
|
||||
@@ -562,7 +867,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
//this occurs because we are supposed to either have a a 'repeat' frame, or 'silent' frame play
|
||||
//due to the error, but the keystream application makes it random 'pfft pop' sound instead
|
||||
if (state->errs < 3)
|
||||
RC4(state->dropL, 9, 7, rckey, cipher, plain);
|
||||
rc4_voice_decrypt(state->dropL, 9, 7, rckey, cipher, plain);
|
||||
else memcpy (plain, cipher, sizeof(plain));
|
||||
|
||||
state->dropL += 7;
|
||||
@@ -602,7 +907,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
//pack cipher byte array from ambe_d bit array
|
||||
pack_ambe(ambe_d, cipher, 49);
|
||||
|
||||
RC4(state->dropL, 13, 7, rckey, cipher, plain);
|
||||
rc4_voice_decrypt(state->dropL, 13, 7, rckey, cipher, plain);
|
||||
state->dropL += 7;
|
||||
|
||||
//unpack deciphered plain array back into ambe_d bit array
|
||||
@@ -638,6 +943,52 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
||||
state->errs2R += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
||||
|
||||
//TYT (Tytera) 16-bit Key (Shuffle/Shift/Inversion Method)
|
||||
if (state->M == 0x16)
|
||||
{
|
||||
//insert an expansion function here
|
||||
unsigned long long int k = 0;
|
||||
uint8_t pNT[56]; memset (pNT, 0, sizeof(pNT));
|
||||
|
||||
//I believe I have this one figured out now
|
||||
//its just a shuffle, shift, invert, shift, invert, shift pattern
|
||||
//could be an lfsr attached, but couldn't figure out the taps
|
||||
|
||||
//below is the pattern found for the 16-bit keys listed on the right
|
||||
// k = 0xFFFF00FFFF00; // 0xFFFF
|
||||
// k = 0x3412CB1234ED; // 0x1234
|
||||
|
||||
//shuffle, invert, shift...and organize into proper key value
|
||||
k = ((state->H & 0xFF) << 8) + ((state->H & 0xFF00) >> 8);
|
||||
k = k << 8 | ((~(state->H & 0xFF) >> 0) & 0xFF);
|
||||
k = k << 16 | state->H;
|
||||
k = k << 8 | ((~(state->H & 0xFF00) >> 8) & 0xFF);
|
||||
|
||||
//debug -- print 48-bit expanded key value
|
||||
fprintf (stderr, "K: %012llX", k);
|
||||
|
||||
for (int j = 0; j < 48; j++)
|
||||
{
|
||||
x = ( ((k << j) & 0x800000000000) >> 47 ) & 1;
|
||||
ambe_d[j] ^= x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Forced 48-bit Keystream Application "Quick and Dirty" XOR
|
||||
if (state->M == 0x48)
|
||||
{
|
||||
// k = 0xD991633EC82E; //F811A5B94C2D ⊻ 2180C6878403 (1234 EP Key)
|
||||
// k = 0x7F5363362BBE; //F811A5B94C2D ⊻ 8742C68F6793 (AAAA EP Key)
|
||||
// k = 0x409231C77C08; (FFFF EP Key)
|
||||
k = state->H;
|
||||
for (int j = 0; j < 48; j++) //49
|
||||
{
|
||||
x = ( ((k << j) & 0x800000000000) >> 47 );
|
||||
ambe_d[j] ^= x;
|
||||
}
|
||||
}
|
||||
|
||||
//EXPERIMENTAL!!
|
||||
//load basic privacy key number from array by the tg value (if not forced)
|
||||
//currently only Moto BP and Hytera 10 Char BP
|
||||
@@ -741,6 +1092,125 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
state->DMRvcR++;
|
||||
}
|
||||
|
||||
//DMR and P25p2 DES-OFB 56 Handling, Slot 2, VCH 1 -- Consider moving into AES handler
|
||||
if ( (state->currentslot == 1 && state->payload_algidR == 0x22 && state->RR != 0) ||
|
||||
(state->currentslot == 1 && state->payload_algidR == 0x81 && state->RR != 0) )
|
||||
{
|
||||
|
||||
//sanity check in case of error
|
||||
if (state->DMRvcR > 17) state->DMRvcR = 17;
|
||||
|
||||
int j; int z = 0; int n = 8; uint8_t b = 0;
|
||||
if (state->DMRvcR == 0)
|
||||
{
|
||||
memset (state->ks_octetR, 0, sizeof(state->ks_octetR));
|
||||
memset (state->ks_bitstreamR, 0, sizeof(state->ks_bitstreamR));
|
||||
state->bit_counterR = 0;
|
||||
|
||||
//check all these comments I'm making for accuracy
|
||||
des_multi_keystream_output (state->payload_miN, state->RR, state->ks_octetR, 1, 19); //18 + 1
|
||||
|
||||
//Load Keystream Octet Bytes directly into a bit array, that way we don't have
|
||||
//to keep track of the byte positions and masks for the 49th bit
|
||||
for (i = 0; i < 18 * 8; i++) //19 blocks minus 1 discard block at 8 bits each
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
b = (( (state->ks_octetR[n] << j) & 0x80) >> 7);
|
||||
state->ks_bitstreamR[z++] = b;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
//now we do the bit by bit xor depending on the frame and position of the state bit counter
|
||||
//run 6 instead of 7 so we can just do bit 49 outside of loop to keep extra bits overloading the array
|
||||
z = 0;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
ambe_d[z++] ^= state->ks_bitstreamR[state->bit_counterR++];
|
||||
}
|
||||
|
||||
//last bit
|
||||
ambe_d[48] ^= state->ks_bitstreamR[state->bit_counterR++];
|
||||
|
||||
//skip the next 7 bits of the array
|
||||
state->bit_counterR += 7;
|
||||
|
||||
//increment vc counter by one
|
||||
state->DMRvcR++;
|
||||
|
||||
}
|
||||
|
||||
//DMR and P25p2 AES, Slot 2, VCH 1
|
||||
if ( (state->currentslot == 1 && state->payload_algidR == 0x24 && state->aes_key_loaded[1] == 1 ) || //DMR AES128
|
||||
(state->currentslot == 1 && state->payload_algidR == 0x25 && state->aes_key_loaded[1] == 1 ) || //DMR AES256
|
||||
(state->currentslot == 1 && state->payload_algidR == 0x89 && state->aes_key_loaded[1] == 1 ) || //P25 AES128
|
||||
(state->currentslot == 1 && state->payload_algidR == 0x84 && state->aes_key_loaded[1] == 1) ) //P25 AES256
|
||||
{
|
||||
|
||||
int j; int z = 0; int n = 16; uint8_t b = 0; //n=16 for AES-OFB discard round
|
||||
uint8_t aes_key[32];
|
||||
memset (aes_key, 0, sizeof(aes_key));
|
||||
|
||||
//Load key from A1 - A4
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
aes_key[i+0] = (state->A1[1] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+8] = (state->A2[1] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+16] = (state->A3[1] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+24] = (state->A4[1] >> (56-(i*8))) & 0xFF;
|
||||
}
|
||||
|
||||
//sanity check in case of error
|
||||
if (state->DMRvcR > 17) state->DMRvcR = 17;
|
||||
|
||||
if (state->DMRvcR == 0)
|
||||
{
|
||||
memset (state->ks_octetR, 0, sizeof(state->ks_octetR));
|
||||
memset (state->ks_bitstreamR, 0, sizeof(state->ks_bitstreamR));
|
||||
state->bit_counterR = 0;
|
||||
|
||||
if (state->payload_algidR == 0x24 || state->payload_algidR == 0x89)
|
||||
aes_ofb_keystream_output (state->aes_ivR, aes_key, state->ks_octetR, 0, 10); //9 + 1 discard round
|
||||
if (state->payload_algidR == 0x25 || state->payload_algidR == 0x84)
|
||||
aes_ofb_keystream_output (state->aes_ivR, aes_key, state->ks_octetR, 2, 10); //9 + 1 discard round
|
||||
|
||||
//Load Keystream Octet Bytes directly into keystream array
|
||||
for (i = 0; i < 9 * 16; i++) //9 rounds at 16 octets
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
b = (( (state->ks_octetR[n] << j) & 0x80) >> 7);
|
||||
state->ks_bitstreamR[z++] = b;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
//now we do the bit by bit xor depending on the frame and position of the state bit counter
|
||||
//run 6 instead of 7 so we can just do bit 49 outside of loop to keep extra bits overloading the array
|
||||
z = 0;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
ambe_d[z++] ^= state->ks_bitstreamR[state->bit_counterR++];
|
||||
}
|
||||
|
||||
//last bit
|
||||
ambe_d[48] ^= state->ks_bitstreamR[state->bit_counterR++];
|
||||
|
||||
//skip the next 7 bits of the array
|
||||
state->bit_counterR += 7;
|
||||
|
||||
//increment vc counter by one
|
||||
state->DMRvcR++;
|
||||
|
||||
opts->dmr_mute_encR = 0; //shim to unmute
|
||||
|
||||
}
|
||||
|
||||
//DMR RC4, Slot 2
|
||||
if (state->currentslot == 1 && state->payload_algidR == 0x21 && state->RR != 0)
|
||||
{
|
||||
@@ -768,7 +1238,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
//this occurs because we are supposed to either have a a 'repeat' frame, or 'silent' frame play
|
||||
//due to the error, but the keystream application makes it random 'pfft pop' sound instead
|
||||
if (state->errsR < 3)
|
||||
RC4(state->dropR, 9, 7, rckey, cipher, plain);
|
||||
rc4_voice_decrypt(state->dropR, 9, 7, rckey, cipher, plain);
|
||||
else memcpy (plain, cipher, sizeof(plain));
|
||||
state->dropR += 7;
|
||||
|
||||
@@ -807,7 +1277,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
//pack cipher byte array from ambe_d bit array
|
||||
pack_ambe(ambe_d, cipher, 49);
|
||||
|
||||
RC4(state->dropR, 13, 7, rckey, cipher, plain);
|
||||
rc4_voice_decrypt(state->dropR, 13, 7, rckey, cipher, plain);
|
||||
state->dropR += 7;
|
||||
|
||||
//unpack deciphered plain array back into ambe_d bit array
|
||||
|
||||
@@ -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"
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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, " ");
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
124
src/p25p1_ldu2.c
124
src/p25p1_ldu2.c
@@ -256,6 +256,9 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
// TODO: do something useful with the LSD bytes... <--THIS!
|
||||
|
||||
state->dropL += 2; //need to skip 2 here for the LSD bytes
|
||||
//same for octet counter
|
||||
state->octet_counter += 2;
|
||||
|
||||
}
|
||||
|
||||
// IMBE 9
|
||||
@@ -277,6 +280,8 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
//reset dropbytes -- skip first 11 for next LCW
|
||||
state->dropL = 267;
|
||||
//reset octet counter
|
||||
state->octet_counter = 0;
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
@@ -476,11 +481,38 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
fprintf (stderr, " LDU2 ALG ID: 0x%02X KEY ID: 0x%04X MI: 0x%08llX%08llX", algidhex, kidhex, mihex1, mihex2);
|
||||
state->payload_algid = algidhex;
|
||||
state->payload_keyid = kidhex;
|
||||
if (mihex3) fprintf (stderr, "-%02llX", mihex3);
|
||||
if (state->R != 0 && state->payload_algid == 0xAA)
|
||||
{
|
||||
fprintf (stderr, " Key: %010llX", state->R);
|
||||
opts->unmute_encrypted_p25 = 1;
|
||||
}
|
||||
else if (state->R != 0 && state->payload_algid == 0x81)
|
||||
{
|
||||
fprintf (stderr, " Key: %010llX", state->R);
|
||||
opts->unmute_encrypted_p25 = 1;
|
||||
}
|
||||
else if (state->R != 0 && state->payload_algid == 0x9F)
|
||||
{
|
||||
fprintf (stderr, " Key: %010llX", state->R);
|
||||
opts->unmute_encrypted_p25 = 1;
|
||||
}
|
||||
/* //going to want to update this for OFB, CBC, and ECB
|
||||
{ 0x84, "AES-256-OFB" },
|
||||
{ 0x85, "AES-128-ECB"},
|
||||
{ 0x88, "AES-CBC"},
|
||||
{ 0x89, "AES-128-OFB"},
|
||||
*/
|
||||
else if ( (state->payload_algid == 0x84 || state->payload_algid == 0x89) && state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]);
|
||||
if (state->payload_algid == 0x84)
|
||||
fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]);
|
||||
fprintf (stderr, "%s ", KNRM);
|
||||
opts->unmute_encrypted_p25 = 1;
|
||||
}
|
||||
else if (state->payload_algid != 0 && state->payload_algid != 0x80)
|
||||
{
|
||||
//may want to mute this again, or may not want to
|
||||
@@ -627,6 +659,15 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
//expand 64-bit MI to 128-bit for AES
|
||||
if (state->payload_algid == 0x84 || state->payload_algid == 0x89)
|
||||
{
|
||||
LFSR128(state);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
//xl, we need to know if the ESS is from HDU, or LDU2
|
||||
state->xl_is_hdu = 0;
|
||||
|
||||
#define P25p1_ENC_LO //disable if this behavior is detremental
|
||||
#ifdef P25p1_ENC_LO
|
||||
@@ -703,3 +744,86 @@ void LFSRP(dsd_state * state)
|
||||
fprintf (stderr, "\n LDU2/ESS_B FEC ERR - ALG: 0x%02X KEY ID: 0x%04X LFSR MI: 0x%016llX", state->payload_algidR, state->payload_keyidR, state->payload_miN);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
|
||||
void LFSR128(dsd_state * state)
|
||||
{
|
||||
//generate a 128-bit IV from a 64-bit IV for AES blocks
|
||||
unsigned long long int lfsr = 0;
|
||||
|
||||
int slot = state->currentslot;
|
||||
|
||||
if (state->currentslot == 0)
|
||||
lfsr = state->payload_miP;
|
||||
else lfsr = state->payload_miN;
|
||||
|
||||
//start packing aes_iv
|
||||
if (slot == 0)
|
||||
{
|
||||
state->aes_iv[0] = (lfsr >> 56) & 0xFF;
|
||||
state->aes_iv[1] = (lfsr >> 48) & 0xFF;
|
||||
state->aes_iv[2] = (lfsr >> 40) & 0xFF;
|
||||
state->aes_iv[3] = (lfsr >> 32) & 0xFF;
|
||||
state->aes_iv[4] = (lfsr >> 24) & 0xFF;
|
||||
state->aes_iv[5] = (lfsr >> 16) & 0xFF;
|
||||
state->aes_iv[6] = (lfsr >> 8 ) & 0xFF;
|
||||
state->aes_iv[7] = (lfsr >> 0 ) & 0xFF;
|
||||
}
|
||||
if (slot == 1)
|
||||
{
|
||||
state->aes_ivR[0] = (lfsr >> 56) & 0xFF;
|
||||
state->aes_ivR[1] = (lfsr >> 48) & 0xFF;
|
||||
state->aes_ivR[2] = (lfsr >> 40) & 0xFF;
|
||||
state->aes_ivR[3] = (lfsr >> 32) & 0xFF;
|
||||
state->aes_ivR[4] = (lfsr >> 24) & 0xFF;
|
||||
state->aes_ivR[5] = (lfsr >> 16) & 0xFF;
|
||||
state->aes_ivR[6] = (lfsr >> 8 ) & 0xFF;
|
||||
state->aes_ivR[7] = (lfsr >> 0 ) & 0xFF;
|
||||
}
|
||||
|
||||
int cnt = 0; int x = 64;
|
||||
unsigned long long int bit;
|
||||
//polynomial P(x) = 1 + X15 + X27 + X38 + X46 + X62 + X64
|
||||
for(cnt=0;cnt<64;cnt++)
|
||||
{
|
||||
//63,61,45,37,27,14
|
||||
// Polynomial is C(x) = x^64 + x^62 + x^46 + x^38 + x^27 + x^15 + 1
|
||||
bit = ((lfsr >> 63) ^ (lfsr >> 61) ^ (lfsr >> 45) ^ (lfsr >> 37) ^ (lfsr >> 26) ^ (lfsr >> 14)) & 0x1;
|
||||
lfsr = (lfsr << 1) | bit;
|
||||
|
||||
//continue packing aes_iv
|
||||
if (slot == 0)
|
||||
state->aes_iv[x/8] = (state->aes_iv[x/8] << 1) + bit;
|
||||
if (slot == 1)
|
||||
state->aes_ivR[x/8] = (state->aes_ivR[x/8] << 1) + bit;
|
||||
x++;
|
||||
}
|
||||
|
||||
if (state->currentslot == 0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
if (state->dmrburstL != 27) //if not LDU2
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " ");
|
||||
fprintf (stderr, " ALG ID: 0x%02X KEY ID: 0x%04X MI(128): 0x", state->payload_algid, state->payload_keyid);
|
||||
for (x = 0; x < 16; x++)
|
||||
fprintf (stderr, "%02X", state->aes_iv[x]);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
// fprintf (stderr, "\n");
|
||||
|
||||
}
|
||||
|
||||
if (state->currentslot == 1)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
if (state->dmrburstL != 27) //if not LDU2, shouldn't matter on P25p2 for the second slot
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " ");
|
||||
fprintf (stderr, " ALG ID: 0x%02X KEY ID: 0x%04X MI(128): 0x", state->payload_algidR, state->payload_keyidR);
|
||||
for (x = 0; x < 16; x++)
|
||||
fprintf (stderr, "%02X", state->aes_ivR[x]);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
// fprintf (stderr, "\n");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
142
src/p25p2_xcch.c
142
src/p25p2_xcch.c
@@ -153,11 +153,28 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
|
||||
if (state->payload_algid != 0x80 && state->payload_algid != 0x0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid);
|
||||
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
|
||||
fprintf (stderr, " MI 0x%016llX", state->payload_miP);
|
||||
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
|
||||
fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algid);
|
||||
fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyid);
|
||||
fprintf (stderr, " MI: 0x%016llX", state->payload_miP);
|
||||
fprintf(stderr, " MPTT");
|
||||
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
|
||||
if (state->R != 0 && state->payload_algid == 0x81) fprintf (stderr, " Key 0x%016llX", state->R);
|
||||
|
||||
if ( (state->payload_algid == 0x84 || state->payload_algid == 0x89) && state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]);
|
||||
if (state->payload_algid == 0x84)
|
||||
fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]);
|
||||
// opts->unmute_encrypted_p25 = 1; //needed?
|
||||
}
|
||||
|
||||
//expand 64-bit MI to 128-bit for AES
|
||||
if (state->payload_algid == 0x84 || state->payload_algid == 0x89)
|
||||
{
|
||||
LFSR128(state);
|
||||
// fprintf (stderr, "\n");
|
||||
}
|
||||
// fprintf (stderr, " %s", KRED);
|
||||
// fprintf (stderr, "ENC");
|
||||
}
|
||||
@@ -195,11 +212,28 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
|
||||
if (state->payload_algidR != 0x80 && state->payload_algidR != 0x0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR);
|
||||
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
|
||||
fprintf (stderr, " MI 0x%016llX", state->payload_miN);
|
||||
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
|
||||
fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algidR);
|
||||
fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyidR);
|
||||
fprintf (stderr, " MI: 0x%016llX", state->payload_miN);
|
||||
fprintf(stderr, " MPTT");
|
||||
|
||||
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
|
||||
if (state->RR != 0 && state->payload_algidR == 0x81) fprintf (stderr, " Key 0x%016llX", state->RR);
|
||||
if ( (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) && state->aes_key_loaded[1] == 1)
|
||||
{
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "Key: %016llX %016llX ", state->A1[1], state->A2[1]);
|
||||
if (state->payload_algidR == 0x84)
|
||||
fprintf (stderr, "%016llX %016llX", state->A3[1], state->A4[1]);
|
||||
// opts->unmute_encrypted_p25 = 1; //needed?
|
||||
}
|
||||
|
||||
//expand 64-bit MI to 128-bit for AES
|
||||
if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89)
|
||||
{
|
||||
LFSR128(state);
|
||||
// fprintf (stderr, "\n");
|
||||
}
|
||||
// fprintf (stderr, " %s", KRED);
|
||||
// fprintf (stderr, "ENC");
|
||||
}
|
||||
@@ -220,6 +254,27 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
|
||||
}
|
||||
}
|
||||
|
||||
//reset voice counter at MAC_PTT (inverted, triple check please)
|
||||
if (state->currentslot == 1 && state->payload_algidR == 0x81)
|
||||
state->DMRvcL = 0;
|
||||
|
||||
if (state->currentslot == 0 && state->payload_algid == 0x81)
|
||||
state->DMRvcR = 0;
|
||||
|
||||
//reset voice counter after 2V (AES 256)
|
||||
if (state->currentslot == 1 && state->payload_algidR == 0x84)
|
||||
state->DMRvcL = 0;
|
||||
|
||||
if (state->currentslot == 0 && state->payload_algid == 0x84)
|
||||
state->DMRvcR = 0;
|
||||
|
||||
//reset voice counter after 2V (AES 128)
|
||||
if (state->currentslot == 1 && state->payload_algidR == 0x89)
|
||||
state->DMRvcL = 0;
|
||||
|
||||
if (state->currentslot == 0 && state->payload_algid == 0x89)
|
||||
state->DMRvcR = 0;
|
||||
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//do not permit MAC_PTT_END with CRC errs, help prevent false positives on calls
|
||||
@@ -538,11 +593,28 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
|
||||
if (state->payload_algid != 0x80 && state->payload_algid != 0x0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algid);
|
||||
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyid);
|
||||
fprintf (stderr, " MI 0x%016llX", state->payload_miP);
|
||||
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
|
||||
fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algid);
|
||||
fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyid);
|
||||
fprintf (stderr, " MI: 0x%016llX", state->payload_miP);
|
||||
fprintf(stderr, " MPTT");
|
||||
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
|
||||
if (state->R != 0 && state->payload_algid == 0x81) fprintf (stderr, " Key 0x%016llX", state->R);
|
||||
|
||||
if ( (state->payload_algid == 0x84 || state->payload_algid == 0x89) && state->aes_key_loaded[0] == 1)
|
||||
{
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]);
|
||||
if (state->payload_algid == 0x84)
|
||||
fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]);
|
||||
// opts->unmute_encrypted_p25 = 1; //needed?
|
||||
}
|
||||
|
||||
//expand 64-bit MI to 128-bit for AES
|
||||
if (state->payload_algid == 0x84 || state->payload_algid == 0x89)
|
||||
{
|
||||
LFSR128(state);
|
||||
// fprintf (stderr, "\n");
|
||||
}
|
||||
// fprintf (stderr, " %s", KRED);
|
||||
// fprintf (stderr, "ENC");
|
||||
}
|
||||
@@ -579,11 +651,28 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
|
||||
if (state->payload_algidR != 0x80 && state->payload_algidR != 0x0)
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, "\n ALG ID 0x%02X", state->payload_algidR);
|
||||
fprintf (stderr, " KEY ID 0x%04X", state->payload_keyidR);
|
||||
fprintf (stderr, " MI 0x%016llX", state->payload_miN);
|
||||
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
|
||||
fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algidR);
|
||||
fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyidR);
|
||||
fprintf (stderr, " MI: 0x%016llX", state->payload_miN);
|
||||
fprintf(stderr, " MPTT");
|
||||
|
||||
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
|
||||
if (state->RR != 0 && state->payload_algidR == 0x81) fprintf (stderr, " Key 0x%016llX", state->RR);
|
||||
if ( (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) && state->aes_key_loaded[1] == 1)
|
||||
{
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "Key: %016llX %016llX ", state->A1[1], state->A2[1]);
|
||||
if (state->payload_algidR == 0x84)
|
||||
fprintf (stderr, "%016llX %016llX", state->A3[1], state->A4[1]);
|
||||
// opts->unmute_encrypted_p25 = 1; //needed?
|
||||
}
|
||||
|
||||
//expand 64-bit MI to 128-bit for AES
|
||||
if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89)
|
||||
{
|
||||
LFSR128(state);
|
||||
// fprintf (stderr, "\n");
|
||||
}
|
||||
// fprintf (stderr, " %s", KRED);
|
||||
// fprintf (stderr, "ENC");
|
||||
}
|
||||
@@ -605,6 +694,27 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
|
||||
}
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
//reset voice counter at MAC_PTT
|
||||
if (state->currentslot == 0 && state->payload_algid == 0x81)
|
||||
state->DMRvcL = 0;
|
||||
|
||||
if (state->currentslot == 1 && state->payload_algidR == 0x81)
|
||||
state->DMRvcR = 0;
|
||||
|
||||
//reset voice counter after 2V (AES 256)
|
||||
if (state->currentslot == 0 && state->payload_algid == 0x84)
|
||||
state->DMRvcL = 0;
|
||||
|
||||
if (state->currentslot == 1 && state->payload_algidR == 0x84)
|
||||
state->DMRvcR = 0;
|
||||
|
||||
//reset voice counter after 2V (AES 128)
|
||||
if (state->currentslot == 0 && state->payload_algid == 0x89)
|
||||
state->DMRvcL = 0;
|
||||
|
||||
if (state->currentslot == 1 && state->payload_algidR == 0x89)
|
||||
state->DMRvcR = 0;
|
||||
|
||||
}
|
||||
if (opcode == 0x2 && err == 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user