Add Crypto Code to m17-decoder-sym.c;

pull/33/head
lwvmobile 2024-06-22 15:01:49 -04:00
rodzic 2d80ef107b
commit d1e1d9eb8e
3 zmienionych plików z 241 dodań i 19 usunięć

Wyświetl plik

@ -38,7 +38,7 @@ uint8_t sig[64]={0}; //ECDSA signature
int dummy=0; //dummy var to make compiler quieter
//encryption
//AES
uint8_t encryption=0;
int aes_type = 1; //1=AES128, 2=AES192, 3=AES256
uint8_t key[32];
@ -516,7 +516,7 @@ int main(int argc, char* argv[])
if(fread(next_data, 16, 1, stdin)<1) finished=1;
}
//encrypt
//AES
if(encryption==2)
{
memcpy(&(next_lsf.meta), iv, 14);
@ -525,6 +525,7 @@ int main(int argc, char* argv[])
aes_ctr_bytewise_payload_crypt(iv, key, data, aes_type);
}
//Scrambler
else if (encryption == 1)
{
scrambler_sequence_generator();
@ -698,10 +699,10 @@ int main(int argc, char* argv[])
//Signatures and AES
//encode debug with -- ./m17-coder-sym -D -K sample_aes_key.txt -s 69b07d7afe7f843e56ecbf536a49461dc5901c975d895bf1649cabff8f9b208b > float.sym
//decode debug with -- cat ../m17-coder/float.sym | ./m17-decoder-sym -s c6c03dd11276aa917e7d83ae16d7f4fbf06f31be5869f9ae8004c329947dc4eeef0d9363653c8edf93e50912c6c515b40e0a8cbeea5e984dbc78e1993c8fbd5d
//decode debug with -- cat ../m17-coder/float.sym | ./m17-decoder-sym -s c6c03dd11276aa917e7d83ae16d7f4fbf06f31be5869f9ae8004c329947dc4eeef0d9363653c8edf93e50912c6c515b40e0a8cbeea5e984dbc78e1993c8fbd5d -K 1234567890ABCDEF7777777777777777FEDCBA09876543218888888888888888
//decode debug with -- m17-fme -r -f float.sym -v 1 -k ../m17-decoder/sample_pub_key.txt -J sample_aes_key.txt
//Signatures and 24-bit Scrambler
//encode debug with -- ./m17-coder-sym -D -k 543210 -s 69b07d7afe7f843e56ecbf536a49461dc5901c975d895bf1649cabff8f9b208b > float.sym
//decode debug with -- cat ../m17-coder/float.sym | ./m17-decoder-sym -s c6c03dd11276aa917e7d83ae16d7f4fbf06f31be5869f9ae8004c329947dc4eeef0d9363653c8edf93e50912c6c515b40e0a8cbeea5e984dbc78e1993c8fbd5d
//decode debug with -- cat ../m17-coder/float.sym | ./m17-decoder-sym -s c6c03dd11276aa917e7d83ae16d7f4fbf06f31be5869f9ae8004c329947dc4eeef0d9363653c8edf93e50912c6c515b40e0a8cbeea5e984dbc78e1993c8fbd5d -k 543210
//decode debug with -- m17-fme -r -f float.sym -v 1 -k ../m17-decoder/sample_pub_key.txt -e 543210

Wyświetl plik

@ -1,5 +1,5 @@
m17-decoder-sym: m17-decoder-sym.c
gcc -O2 -Wall -Wextra m17-decoder-sym.c ../../micro-ecc/uECC.c -o m17-decoder-sym -lm -lm17
gcc -O2 -Wall -Wextra m17-decoder-sym.c ../../micro-ecc/uECC.c ../../tinier-aes/aes.c -o m17-decoder-sym -lm -lm17
install:
sudo cp m17-decoder-sym /usr/local/bin

Wyświetl plik

@ -7,6 +7,8 @@
#include "../../libm17/m17.h"
//micro-ecc
#include "../../micro-ecc/uECC.h"
//tinier-aes
#include "../../tinier-aes/aes.h"
//settings
uint8_t decode_callsigns=0;
@ -42,6 +44,87 @@ uint8_t signed_str=0; //is the stream signed?
uint8_t pub_key[64]={0}; //public key
uint8_t sig[64]={0}; //ECDSA signature
//AES
uint8_t encryption=0;
int aes_type = 1; //1=AES128, 2=AES192, 3=AES256
uint8_t key[32];
uint8_t iv[16];
time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC
//Scrambler
uint8_t scr_bytes[16];
uint8_t scrambler_pn[128];
uint32_t scrambler_seed=0;
int8_t scrambler_subtype = -1;
//debug mode
uint8_t debug_mode=0; //TODO: Remove lines looking at this
//scrambler pn sequence generation
void scrambler_sequence_generator()
{
int i = 0;
uint32_t lfsr, bit;
lfsr = scrambler_seed;
//only set if not initially set (first run), it is possible (and observed) that the scrambler_subtype can
//change on subsequent passes if the current SEED for the LFSR falls below one of these thresholds
if (scrambler_subtype == -1)
{
if (lfsr > 0 && lfsr <= 0xFF) scrambler_subtype = 0; // 8-bit key
else if (lfsr > 0xFF && lfsr <= 0xFFFF) scrambler_subtype = 1; //16-bit key
else if (lfsr > 0xFFFF && lfsr <= 0xFFFFFF) scrambler_subtype = 2; //24-bit key
else scrambler_subtype = 0; // 8-bit key (default)
}
//TODO: Set Frame Type based on scrambler_subtype value
if (debug_mode > 1)
{
fprintf (stderr, "\nScrambler Key: 0x%06X; Seed: 0x%06X; Subtype: %02d;", scrambler_seed, lfsr, scrambler_subtype);
fprintf (stderr, "\n pN: ");
}
//run pN sequence with taps specified
for (i = 0; i < 128; i++)
{
//get feedback bit with specified taps, depending on the scrambler_subtype
if (scrambler_subtype == 0)
bit = (lfsr >> 7) ^ (lfsr >> 5) ^ (lfsr >> 4) ^ (lfsr >> 3);
else if (scrambler_subtype == 1)
bit = (lfsr >> 15) ^ (lfsr >> 14) ^ (lfsr >> 12) ^ (lfsr >> 3);
else if (scrambler_subtype == 2)
bit = (lfsr >> 23) ^ (lfsr >> 22) ^ (lfsr >> 21) ^ (lfsr >> 16);
else bit = 0; //should never get here, but just in case
bit &= 1; //truncate bit to 1 bit (required since I didn't do it above)
lfsr = (lfsr << 1) | bit; //shift LFSR left once and OR bit onto LFSR's LSB
lfsr &= 0xFFFFFF; //truncate lfsr to 24-bit (really doesn't matter)
scrambler_pn[i] = bit;
}
//pack bit array into byte array for easy data XOR
pack_bit_array_into_byte_array(scrambler_pn, scr_bytes, 16);
//save scrambler seed for next round
scrambler_seed = lfsr;
//truncate seed so subtype will continue to set properly on subsequent passes
if (scrambler_subtype == 0) scrambler_seed &= 0xFF;
if (scrambler_subtype == 1) scrambler_seed &= 0xFFFF;
if (scrambler_subtype == 2) scrambler_seed &= 0xFFFFFF;
else scrambler_seed &= 0xFF;
if (debug_mode > 1)
{
//debug packed bytes
for (i = 0; i < 16; i++)
fprintf (stderr, " %02X", scr_bytes[i]);
fprintf (stderr, "\n");
}
}
void usage(void)
{
fprintf(stderr, "Usage:\n");
@ -51,6 +134,8 @@ void usage(void)
fprintf(stderr, "-l - Display LSF CRC checks,\n");
fprintf(stderr, "-d - Set syncword detection threshold (decimal value),\n");
fprintf(stderr, "-s - Public key for ECDSA signature, 64 bytes (-s [hex_string|key_file]),\n");
fprintf(stderr, "-K - AES encryption key (-K [hex_string|text_file]),\n");
fprintf(stderr, "-k - Scrambler encryption seed value (-k [hex_string]),\n");
fprintf(stderr, "-h - help / print usage\n");
}
@ -161,6 +246,120 @@ int main(int argc, char* argv[])
i++;
}
//Woj: There is a bug in loading keys this way, I think
// it is to do with how scannign args is different here than in the encoder?
//when loading by file, the key is shifted by one char
//when loading the hex value, though, it works fine.
if(argv[i][1]=='K') //-K - AES Encryption
{
if(strstr(argv[i+1], ".")) //if the next arg contains a dot - read key from a text file
{
char fname[128]={'\0'}; //output file
if(strlen(&argv[i+1][0])>0)
memcpy(fname, &argv[i+1][0], strlen(argv[i+1]));
else
{
fprintf(stderr, "Invalid filename. Exiting...\n");
return -1;
}
FILE* fp;
char source_str[64];
fp = fopen(fname, "r");
if(!fp)
{
fprintf(stderr, "Failed to load file %s.\n", fname);
return -1;
}
//size check
size_t len = fread(source_str, 1, 64, fp); //TODO: check length
fclose(fp);
if(len==256/4)
fprintf(stderr, "AES256");
else if(len==192/4)
fprintf(stderr, "AES192");
else if(len==128/4)
fprintf(stderr, "AES128");
else
{
fprintf(stderr, "Invalid key length.\n");
return -1;
}
parse_raw_key_string(key, source_str);
fprintf(stderr, " key:");
for(uint8_t i=0; i<len/2; i++)
{
if(i==16)
fprintf(stderr, "\n ");
fprintf(stderr, " %02X", key[i]);
}
fprintf(stderr, "\n");
}
else
{
//size check
size_t len = strlen(argv[i+1]);
if(len==256/4)
fprintf(stderr, "AES256");
else if(len==192/4)
fprintf(stderr, "AES192");
else if(len==128/4)
fprintf(stderr, "AES128");
else
{
fprintf(stderr, "Invalid key length.\n");
return -1;
}
parse_raw_key_string(key, argv[i+1]);
fprintf(stderr, " key:");
for(uint8_t i=0; i<len/2; i++)
{
if(i==16)
fprintf(stderr, "\n ");
fprintf(stderr, " %02X", key[i]);
}
fprintf(stderr, "\n");
}
encryption=2; //AES key was passed
}
if(argv[i][1]=='k') //-k - Scrambler Encryption
{
//length check
uint8_t length=strlen(argv[i+1]);
if(length==0 || length>24/4) //24-bit is the largest seed value
{
fprintf(stderr, "Invalid key length.\n");
return -1;
}
parse_raw_key_string(key, argv[i+1]);
scrambler_seed = (key[0] << 16) | (key[1] << 8) | (key[2] << 0);
if(length<=2)
{
scrambler_seed = scrambler_seed >> 16;
fprintf(stderr, "Scrambler key: 0x%02X (8-bit)\n", scrambler_seed);
}
else if(length<=4)
{
scrambler_seed = scrambler_seed >> 8;
fprintf(stderr, "Scrambler key: 0x%04X (16-bit)\n", scrambler_seed);
}
else
fprintf(stderr, "Scrambler key: 0x%06X (24-bit)\n", scrambler_seed);
encryption=1; //Scrambler key was passed
}
if(!strcmp(argv[i], "-l"))
{
@ -250,6 +449,42 @@ int main(int argc, char* argv[])
uint16_t type=(uint16_t)lsf[12]*0x100+lsf[13]; //big-endian
signed_str=(type>>11)&1;
///if the stream is signed (process before decryption)
if(signed_str && fn<0x7FFC)
{
if(fn==0)
memset(digest, 0, sizeof(digest));
for(uint8_t i=0; i<sizeof(digest); i++)
digest[i]^=frame_data[3+i];
uint8_t tmp=digest[0];
for(uint8_t i=0; i<sizeof(digest)-1; i++)
digest[i]=digest[i+1];
digest[sizeof(digest)-1]=tmp;
}
//NOTE: Don't attempt decryption when a signed stream is >= 0x7FFC
//The Signature is not encrypted
//AES
if (encryption == 2 && fn<0x7FFC)
{
memcpy(iv, lsf+14, 14);
iv[14] = frame_data[1] & 0x7F;
iv[15] = frame_data[2] & 0xFF;
aes_ctr_bytewise_payload_crypt(iv, key, frame_data+3, aes_type);
}
//Scrambler
if (encryption == 1 && fn<0x7FFC)
{
scrambler_sequence_generator();
for(uint8_t i=0; i<16; i++)
{
frame_data[i+3] ^= scr_bytes[i];
}
}
//dump data - first byte is empty
printf("FN: %04X PLD: ", fn);
for(uint8_t i=3; i<19; i++)
@ -264,20 +499,6 @@ int main(int argc, char* argv[])
//send codec2 stream to stdout
//fwrite(&frame_data[3], 16, 1, stdout);
//if the stream is signed
if(signed_str && fn<0x7FFC)
{
if(fn==0)
memset(digest, 0, sizeof(digest));
for(uint8_t i=0; i<sizeof(digest); i++)
digest[i]^=frame_data[3+i];
uint8_t tmp=digest[0];
for(uint8_t i=0; i<sizeof(digest)-1; i++)
digest[i]=digest[i+1];
digest[sizeof(digest)-1]=tmp;
}
//extract LICH
for(uint16_t i=0; i<96; i++)
{