From 65b1f62e51ea3e2348869b29361a65eb7588d45d Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 12 Jun 2024 05:10:29 -0400 Subject: [PATCH 01/33] User Input Strings for SMS and Raw Hex Octets; README Update; Misc Output Formatting Tweaks; --- README.md | 101 ++++++++++++------ SP5WWP/m17-packet/m17-packet-decode.c | 12 ++- SP5WWP/m17-packet/m17-packet-encode.c | 146 ++++++++++++++++++++++---- 3 files changed, 198 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index f2c96fd..2403ba9 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,9 @@ Packet encoding is available with `m17-packet-encoder`. Its input parameters are -S - source callsign (uppercase alphanumeric string) max. 9 characters -D - destination callsign (uppercase alphanumeric string) or ALL for broadcast -C - Channel Access Number (0..15, default - 0) --n - number of bytes (1 to 798) +-T - SMS Text Message (example: -T 'Hello World! This is a text message') +-R - Raw Hex Octets (example: -R 010203040506070809) +-n - number of bytes, only when pre-encoded data passed over stdin (1 to 798) -o - output file path/name -x - binary output (M17 baseband as a packed bitstream) -r - raw audio output - default (single channel, signed 16-bit LE, +7168 for the +1.0 symbol, 10 samples per symbol) @@ -87,7 +89,7 @@ Packet encoding is available with `m17-packet-encoder`. Its input parameters are -w - libsndfile wav audio output - default (single channel, signed 16-bit LE, +7168 for the +1.0 symbol, 10 samples per symbol) ``` -Input data is passed over stdin. Example command: +Input data can be pre-encoded and passed over stdin. Example command: `echo -en "\x05Testing M17 packet mode.\x00" | ./m17-packet-encode -S N0CALL -D ALL -C 0 -n 26 -f -o baseband.sym` @@ -97,16 +99,16 @@ Input data is passed over stdin. Example command: Output: ``` -DST: ALL FFFFFFFFFFFF -SRC: N0CALL 00004B13D106 -Data CRC: BFEC -LSF CRC: 432A +SMS: Testing M17 packet mode. +DST: ALL FFFFFFFFFFFF +SRC: N0CALL 00004B13D106 +CAN: 00 +Data CRC: BFEC +LSF CRC: 432A FN:00 (full frame) -0554657374696E67204D3137207061636B6574206D6F64652E00 FN:-- (ending frame) -00BFEC0000000000000000000000000000000000000000000084 -FULL: 0554657374696E67204D3137207061636B6574206D6F64652E00BFEC - SMS: Testing M17 packet mode. +PKT: 05 54 65 73 74 69 6E 67 20 4D 31 37 20 70 61 63 6B 65 74 20 6D 6F 64 65 2E + 00 BF EC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` Decode packet created with above sample: @@ -117,26 +119,28 @@ Output: ``` DST: FFFFFFFFFFFF SRC: 00004B13D106 TYPE: 0002 META: 0000000000000000000000000000 LSF_CRC_OK -Testing M17 packet mode. +SMS: Testing M17 packet mode. ``` -Encode directly as wav format (skip sox): +Encode User Text String as wav format: -`echo -en "\x05Testing M17 packet mode.\x00" | ./m17-packet-encode -S N0CALL -D AB1CDE -C 7 -n 26 -w -o baseband.wav` +`./m17-packet-encode -S N0CALL -D AB1CDE -T 'This is an SMS Text Message Generated by m17-packet-encode' -C 7 -w -o baseband.wav` Output: ``` -DST: AB1CDE 00001F245D51 -SRC: N0CALL 00004B13D106 -Data CRC: BFEC -LSF CRC: F754 +SMS: This is an SMS Text Message Generated by m17-packet-encode +DST: AB1CDE 00001F245D51 +SRC: N0CALL 00004B13D106 +CAN: 07 +Data CRC: FD81 +LSF CRC: F754 FN:00 (full frame) -0554657374696E67204D3137207061636B6574206D6F64652E00 +FN:01 (full frame) FN:-- (ending frame) -00BFEC0000000000000000000000000000000000000000000084 -FULL: 0554657374696E67204D3137207061636B6574206D6F64652E00BFEC - SMS: Testing M17 packet mode. +PKT: 05 54 68 69 73 20 69 73 20 61 6E 20 53 4D 53 20 54 65 78 74 20 4D 65 73 73 + 61 67 65 20 47 65 6E 65 72 61 74 65 64 20 62 79 20 6D 31 37 2D 70 61 63 6B + 65 74 2D 65 6E 63 6F 64 65 00 FD 81 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` Decode with M17-FME: @@ -147,26 +151,55 @@ Output: ``` M17 Project - Florida Man Edition -Build Version: 2024-1-g4f2c15c -Session Number: A4F5 +Build Version: 2024-10-g060dd21 +Session Number: A751 M17 Project RF Audio Frame Demodulator. SNDFile (.wav, .rrc) Input File: baseband.wav Payload Verbosity: 1; -M17 LSF Frame Sync (08:57:09): - DST: AB1CDE SRC: N0CALL CAN: 7; Data Packet +M17 LSF Frame Sync (16:12:34): + DST: AB1CDE SRC: N0CALL CAN: 7; Data Packet FT: 0382; ET: 0; ES: 0; LSF: 00 00 1F 24 5D 51 00 00 4B 13 D1 06 03 82 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F7 54 (CRC CHK) E: F754; C: F754; -M17 PKT Frame Sync (08:57:09): CNT: 00; PBC: 00; EOT: 0; - pkt: 0554657374696E67204D3137207061636B6574206D6F64652E00 -M17 PKT Frame Sync (08:57:09): CNT: 01; LST: 01; EOT: 1; - pkt: 00BFEC0000000000000000000000000000000000000000000084 Protocol: SMS; - SMS: Testing M17 packet mode. - PKT: 05 54 65 73 74 69 6E 67 20 4D 31 37 20 70 61 63 6B 65 74 20 6D 6F 64 65 2E - 00 BF EC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - (CRC CHK) E: BFEC; C: BFEC; -M17 No Frame Sync (08:57:09): +M17 PKT Frame Sync (16:12:34): CNT: 00; PBC: 00; EOT: 0; + pkt: 055468697320697320616E20534D532054657874204D65737300 +M17 PKT Frame Sync (16:12:34): CNT: 01; PBC: 01; EOT: 0; + pkt: 6167652047656E657261746564206279206D31372D7061636B04 +M17 PKT Frame Sync (16:12:34): CNT: 02; LST: 12; EOT: 1; + pkt: 65742D656E636F646500FD8100000000000000000000000000B0 Protocol: SMS; + SMS: This is an SMS Text Message Generated by m17-packet-encode + PKT: 05 54 68 69 73 20 69 73 20 61 6E 20 53 4D 53 20 54 65 78 74 20 4D 65 73 73 + 61 67 65 20 47 65 6E 65 72 61 74 65 64 20 62 79 20 6D 31 37 2D 70 61 63 6B + 65 74 2D 65 6E 63 6F 64 65 00 FD 81 00 00 00 00 00 00 00 00 00 00 00 00 00 + (CRC CHK) E: FD81; C: FD81; +``` +Encode Raw Hex Octet String as float symbol format: + +`./m17-packet-encode -S N0CALL -D AB1CDE -R 010203040506070809 -C 7 -f -o float.sym` + +Output: + +``` +Raw Len: 9; Raw Octets: 01 02 03 04 05 06 07 08 09 +DST: AB1CDE 00001F245D51 +SRC: N0CALL 00004B13D106 +CAN: 07 +Data CRC: D7CE +LSF CRC: F754 +FN:-- (ending frame) +PKT: 01 02 03 04 05 06 07 08 09 D7 CE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +``` + +Decode (rolling) packets created with above sample: + +`tail -f float.sym | ./m17-packet-decode` + +Output: + +``` +DST: 00001F245D51 SRC: 00004B13D106 TYPE: 0382 META: 0000000000000000000000000000 LSF_CRC_OK +PKT: 01 02 03 04 05 06 07 08 09 D7 CE ``` \ No newline at end of file diff --git a/SP5WWP/m17-packet/m17-packet-decode.c b/SP5WWP/m17-packet/m17-packet-decode.c index f0ba2c1..a4cf127 100644 --- a/SP5WWP/m17-packet/m17-packet-decode.c +++ b/SP5WWP/m17-packet/m17-packet-decode.c @@ -207,10 +207,10 @@ int main(int argc, char* argv[]) { uint16_t p_len=strlen((const char*)packet_data); uint16_t p_crc=CRC_M17(packet_data, p_len+1); - fprintf(stderr, "Data CRC: rx=%02X%02X calc=%04X\n ", packet_data[p_len+1], packet_data[p_len+2], p_crc); + fprintf(stderr, "Data CRC: rx=%02X%02X calc=%04X\n", packet_data[p_len+1], packet_data[p_len+2], p_crc); if(p_crc==(uint16_t)packet_data[p_len+1]*256+(uint16_t)packet_data[p_len+2]) { - fprintf(stderr, "%s\n", &packet_data[1]); + fprintf(stderr, "SMS: %s\n", &packet_data[1]); } } } @@ -218,10 +218,12 @@ int main(int argc, char* argv[]) { if(!text_only) { - fprintf(stderr, "PKT: "); - for(uint16_t i=0; i 797) len = 797; + + //set num_bytes to len + 1 + num_bytes = len + 0; //doing 0 instead, let user pass an extra 00 on the end if they want it there + + char octet_char[3]; + octet_char[2] = 0; + uint16_t k = 0; + uint16_t i = 0; + + //debug + fprintf (stderr, "\nRaw Len: %d; Raw Octets:", len); + + for (i = 0; i < len; i++) + { + strncpy (octet_char, input+k, 2); + octet_char[2] = 0; + sscanf (octet_char, "%hhX", &raw[i]); + + //debug + // fprintf (stderr, " (%s)", octet_char); + fprintf (stderr, " %02X", raw[i]); + + k += 2; + } + + fprintf (stderr, "\n"); +} + //main routine int main(int argc, char* argv[]) { //scan command line options for input data - //TODO: support for strings with spaces, the code below is NOT foolproof! - //the user has to provide a minimum of 2 parameters: number of bytes and output filename + //WIP: support for text strings with spaces and raw hex octet strings (still NOT foolproof) + //the user has to provide a minimum of 2 parameters: input string or num_bytes, output type, and output filename if(argc>=4) { for(uint8_t i=1; i0) + { + memset(text, 0, 800*sizeof(char)); + memcpy(text, &argv[i+1][0], strlen(argv[i+1])); + std_encode = 0; + sms_encode = 1; + raw_encode = 0; + } + } + else if(argv[i][1]=='R') //-R - Raw Octets + { + if(strlen(&argv[i+1][0])>0) + { + memset (raw, 0, sizeof(raw)); + parse_raw_user_string (argv[i+1]); + std_encode = 0; + sms_encode = 0; + raw_encode = 1; + } + } else if(argv[i][1]=='o') //-o - output filename { if(strlen(&argv[i+1][0])>0) @@ -187,7 +262,9 @@ int main(int argc, char* argv[]) fprintf(stderr, "-S - source callsign (uppercase alphanumeric string) max. 9 characters,\n"); fprintf(stderr, "-D - destination callsign (uppercase alphanumeric string) or ALL for broadcast,\n"); fprintf(stderr, "-C - Channel Access Number (0..15, default - 0),\n"); - fprintf(stderr, "-n - number of bytes (1 to 798),\n"); + fprintf(stderr, "-T - SMS Text Message (example: -T 'Hello World! This is a text message'),\n"); + fprintf(stderr, "-R - Raw Hex Octets (example: -R 010203040506070809),\n"); + fprintf(stderr, "-n - number of bytes, only when pre-encoded data passed over stdin (1 to 798),\n"); fprintf(stderr, "-o - output file path/name,\n"); fprintf(stderr, "Output formats:\n"); //fprintf(stderr, "-x - binary output (M17 baseband as a packed bitstream),\n"); @@ -199,13 +276,8 @@ int main(int argc, char* argv[]) return -1; } - //assert number of bytes and filename - if(num_bytes==0) - { - fprintf(stderr, "Number of bytes not set. Exiting...\n"); - return -1; - } - else if(strlen((const char*)fname)==0) + //assert filename and not binary output + if(strlen((const char*)fname)==0) { fprintf(stderr, "Filename not specified. Exiting...\n"); return -1; @@ -218,12 +290,43 @@ int main(int argc, char* argv[]) //obtain data and append with CRC memset(full_packet_data, 0, 32*25); - if(fread(full_packet_data, num_bytes, 1, stdin)<1) + + //SMS Encode (-T) ./m17-packet-encode -f -o float.sym -T 'This is a simple SMS text message sent over M17 Packet Data.' + if (sms_encode == 1) { - fprintf(stderr, "Packet data too short. Exiting...\n"); - return -1; + num_bytes = strlen((const char*)text); //No need to check for zero return, since the default text string is supplied + if (num_bytes > 796) num_bytes = 796; //not 798 because we have to manually add the 0x05 protocol byte and 0x00 terminator + full_packet_data[0] = 0x05; //SMS Protocol + memcpy (full_packet_data+1, text, num_bytes); + num_bytes+= 2; //add one for terminating byte and 1 for strlen fix + fprintf (stderr, "SMS: %s\n", full_packet_data+1); } - + + //RAW Encode (-R) ./m17-packet-encode -f -o float.sym -R 5B69001E135152397C0A0000005A45 + else if (raw_encode == 1) + { + memcpy (full_packet_data, raw, num_bytes); + } + + //Old Method pre-encoded data over stdin // echo -en "\x05Testing M17 packet mode.\x00" | ./m17-packet-encode -S N0CALL -D AB1CDE -C 7 -n 26 -f -o float.sym + else if (std_encode == 1) + { + //assert number of bytes + if(num_bytes==0) + { + fprintf(stderr, "Number of bytes not set. Exiting...\n"); + return -1; + } + + if(fread(full_packet_data, num_bytes, 1, stdin)<1) + { + fprintf(stderr, "Packet data too short. Exiting...\n"); + return -1; + } + fprintf(stderr, "SMS: %s\n", full_packet_data+1); + // + } + uint16_t packet_crc=CRC_M17(full_packet_data, num_bytes); full_packet_data[num_bytes] =packet_crc>>8; full_packet_data[num_bytes+1]=packet_crc&0xFF; @@ -244,8 +347,7 @@ int main(int argc, char* argv[]) #else fprintf(stderr, "DST: %s\t%012lX\nSRC: %s\t%012lX\n", dst_raw, dst_encoded, src_raw, src_encoded); #endif - //fprintf(stderr, "DST: %02X %02X %02X %02X %02X %02X\n", lsf.dst[0], lsf.dst[1], lsf.dst[2], lsf.dst[3], lsf.dst[4], lsf.dst[5]); - //fprintf(stderr, "SRC: %02X %02X %02X %02X %02X %02X\n", lsf.src[0], lsf.src[1], lsf.src[2], lsf.src[3], lsf.src[4], lsf.src[5]); + fprintf(stderr, "CAN: %02d\n", can); fprintf(stderr, "Data CRC:\t%04hX\n", packet_crc); type=((uint16_t)0x01<<1)|((uint16_t)can<<7); //packet mode, content: data lsf.type[0]=(uint16_t)type>>8; @@ -368,16 +470,16 @@ int main(int argc, char* argv[]) } num_bytes=tmp; //bring back the num_bytes value - - fprintf (stderr, "FULL: "); - for(uint8_t i=0; i Date: Wed, 12 Jun 2024 16:42:51 +0200 Subject: [PATCH 02/33] WIP AES encryption --- .gitmodules | 3 +++ tiny-AES-c | 1 + 2 files changed, 4 insertions(+) create mode 160000 tiny-AES-c diff --git a/.gitmodules b/.gitmodules index ae11332..68b3a3f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "libm17"] path = libm17 url = https://github.com/M17-Project/libm17 +[submodule "tiny-AES-c"] + path = tiny-AES-c + url = https://github.com/kokke/tiny-AES-c diff --git a/tiny-AES-c b/tiny-AES-c new file mode 160000 index 0000000..f06ac37 --- /dev/null +++ b/tiny-AES-c @@ -0,0 +1 @@ +Subproject commit f06ac37fc31dfdaca2e0d9bec83f90d5663c319b From c16c142047e61720cf1c90b9d10a7ac35db5959c Mon Sep 17 00:00:00 2001 From: Wojciech Kaczmarski Date: Wed, 12 Jun 2024 16:43:15 +0200 Subject: [PATCH 03/33] WIP AES encryption --- SP5WWP/m17-coder/Makefile | 2 +- SP5WWP/m17-coder/m17-coder-sym.c | 52 ++++++++++++++++++++++++++++++-- tiny-AES-c | 2 +- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/SP5WWP/m17-coder/Makefile b/SP5WWP/m17-coder/Makefile index e6e6d5f..ff87f94 100644 --- a/SP5WWP/m17-coder/Makefile +++ b/SP5WWP/m17-coder/Makefile @@ -1,5 +1,5 @@ m17-coder-sym: m17-coder-sym.c - gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym.c -o m17-coder-sym -lm -lm17 + gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym.c ../../tiny-AES-c/aes.c -o m17-coder-sym -lm -lm17 clean: rm -f m17-coder-sym diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index eeede3b..5f2c46e 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -2,9 +2,12 @@ #include #include #include +#include //libm17 #include +//tiny-AES-c +#include "../../tiny-AES-c/aes.h" //#define FN60_DEBUG @@ -24,18 +27,45 @@ uint8_t lich_cnt=0; //0..5 LICH counter uint8_t got_lsf=0; //have we filled the LSF struct yet? uint8_t finished=0; +//encryption +uint8_t encryption=0; +struct AES_ctx ctx; +uint8_t key[AES_KEYLEN]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; //TODO: replace with a `-K` arg key entry +uint8_t iv[AES_BLOCKLEN]; +time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC + //main routine -int main(void) +int main(int argc, char* argv[]) { //debug //printf("%06X\n", golay24_encode(1)); //golay encoder codeword test //printf("%d -> %d -> %d\n", 1, intrl_seq[1], intrl_seq[intrl_seq[1]]); //interleaver bijective reciprocality test, f(f(x))=x //return 0; + //encryption init + if(argc>2 && strstr(argv[1], "-K")) + encryption=2; //AES key was passed + + if(encryption==2) + { + //TODO: read key + AES_init_ctx(&ctx, key); + *((int32_t*)&iv[0])=(uint32_t)time(NULL)-(uint32_t)epoch; //timestamp + for(uint8_t i=4; i<4+10; i++) iv[i]=0; //10 random bytes TODO: replace with a rand() or pass through an additional arg + } + if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; + if(encryption==0) + { + if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //read data from stdin + } + else + { + memcpy(&(next_lsf.meta), iv, 14); //AES encryption enabled - use 112 bits of IV + finished=1; + } if(fread(next_data, 16, 1, stdin)<1) finished=1; while(!finished) @@ -56,7 +86,15 @@ int main(void) if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; + if(encryption==0) + { + if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //read data from stdin + } + else + { + memcpy(&(next_lsf.meta), iv, 14); //AES encryption enabled - use 112 bits of IV + finished=1; + } if(fread(next_data, 16, 1, stdin)<1) finished=1; if(got_lsf) //stream frames @@ -74,6 +112,14 @@ int main(void) //unpack LICH (12 bytes) unpack_LICH(enc_bits, lich_encoded); + //encrypt + if(encryption==2) + { + *((uint16_t*)&iv[14])=fn; + AES_ctx_set_iv(&ctx, iv); //re-init IV (update FN) + AES_CTR_xcrypt_buffer(&ctx, data, AES_BLOCKLEN); + } + //encode the rest of the frame (starting at bit 96 - 0..95 are filled with LICH) conv_encode_stream_frame(&enc_bits[96], data, finished ? (fn | 0x8000) : fn); diff --git a/tiny-AES-c b/tiny-AES-c index f06ac37..a192caa 160000 --- a/tiny-AES-c +++ b/tiny-AES-c @@ -1 +1 @@ -Subproject commit f06ac37fc31dfdaca2e0d9bec83f90d5663c319b +Subproject commit a192caa973c84828ad7bc4de74351a3a4729d930 From d1ee6c64846b610181bf889a760ca56d65575e6d Mon Sep 17 00:00:00 2001 From: Wojciech Kaczmarski Date: Wed, 12 Jun 2024 16:51:33 +0200 Subject: [PATCH 04/33] tiny-AES-c update --- tiny-AES-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiny-AES-c b/tiny-AES-c index a192caa..f06ac37 160000 --- a/tiny-AES-c +++ b/tiny-AES-c @@ -1 +1 @@ -Subproject commit a192caa973c84828ad7bc4de74351a3a4729d930 +Subproject commit f06ac37fc31dfdaca2e0d9bec83f90d5663c319b From 917f1738deebde24c7b147a20f567f1f1a7a3c80 Mon Sep 17 00:00:00 2001 From: Wojciech Kaczmarski Date: Wed, 12 Jun 2024 16:56:21 +0200 Subject: [PATCH 05/33] tiny-AES-c update --- tiny-AES-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiny-AES-c b/tiny-AES-c index f06ac37..de4de68 160000 --- a/tiny-AES-c +++ b/tiny-AES-c @@ -1 +1 @@ -Subproject commit f06ac37fc31dfdaca2e0d9bec83f90d5663c319b +Subproject commit de4de68369665dfd907964d3150be212e0549422 From 96e30ae846bf6f2e3afb75a536ef42a255e48e0b Mon Sep 17 00:00:00 2001 From: Wojciech Kaczmarski Date: Fri, 14 Jun 2024 10:24:56 +0200 Subject: [PATCH 06/33] fix? --- tiny-AES-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiny-AES-c b/tiny-AES-c index de4de68..f06ac37 160000 --- a/tiny-AES-c +++ b/tiny-AES-c @@ -1 +1 @@ -Subproject commit de4de68369665dfd907964d3150be212e0549422 +Subproject commit f06ac37fc31dfdaca2e0d9bec83f90d5663c319b From 7280cf0f7e8bc187de74df257810d4df9d9139cf Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sat, 15 Jun 2024 13:03:41 -0400 Subject: [PATCH 07/33] Packet Encoder: Fix num_bytes>=25 to num_bytes>25 so when a frame or remainder is exactly 25, it is still the final frame, and produces the EOT bit; --- SP5WWP/m17-packet/m17-packet-encode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SP5WWP/m17-packet/m17-packet-encode.c b/SP5WWP/m17-packet/m17-packet-encode.c index 08d1bb3..5ae455b 100644 --- a/SP5WWP/m17-packet/m17-packet-encode.c +++ b/SP5WWP/m17-packet/m17-packet-encode.c @@ -398,7 +398,10 @@ int main(int argc, char* argv[]) //send packet frame syncword fill_syncword(full_packet, &pkt_sym_cnt, SYNC_PKT); - if(num_bytes>=25) + //the following examples produce exactly 25 bytes, which exactly one frame, but >= meant this would never produce a final frame with EOT bit set + //echo -en "\x05Testing M17 packet mo\x00" | ./m17-packet-encode -S N0CALL -D ALL -C 10 -n 23 -o float.sym -f + //./m17-packet-encode -S N0CALL -D ALL -C 10 -o float.sym -f -T 'this is a simple text' + if(num_bytes>25) //fix for frames that, with terminating byte and crc, land exactly on 25 bytes (or %25==0) { memcpy(pkt_chunk, &full_packet_data[pkt_cnt*25], 25); pkt_chunk[25]=pkt_cnt<<2; From 20c759d88500d0c745eaebc3ef03f88e2d5d113d Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sun, 16 Jun 2024 12:16:09 -0400 Subject: [PATCH 08/33] Update Submodule to tinier-aes and changes to coder to use its wrapper function; --- .gitmodules | 6 +++--- SP5WWP/m17-coder/Makefile | 2 +- SP5WWP/m17-coder/m17-coder-sym.c | 15 +++++++-------- tiny-AES-c | 1 - 4 files changed, 11 insertions(+), 13 deletions(-) delete mode 160000 tiny-AES-c diff --git a/.gitmodules b/.gitmodules index 68b3a3f..cba3a1e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "libm17"] path = libm17 url = https://github.com/M17-Project/libm17 -[submodule "tiny-AES-c"] - path = tiny-AES-c - url = https://github.com/kokke/tiny-AES-c +[submodule "tinier-aes"] + path = tinier-aes + url = https://github.com/lwvmobile/tinier-aes diff --git a/SP5WWP/m17-coder/Makefile b/SP5WWP/m17-coder/Makefile index ff87f94..e6e6d5f 100644 --- a/SP5WWP/m17-coder/Makefile +++ b/SP5WWP/m17-coder/Makefile @@ -1,5 +1,5 @@ m17-coder-sym: m17-coder-sym.c - gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym.c ../../tiny-AES-c/aes.c -o m17-coder-sym -lm -lm17 + gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym.c -o m17-coder-sym -lm -lm17 clean: rm -f m17-coder-sym diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 5f2c46e..ab3520e 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -6,8 +6,8 @@ //libm17 #include -//tiny-AES-c -#include "../../tiny-AES-c/aes.h" +//tinier-aes +#include "../../tinier-aes/aes.c" //#define FN60_DEBUG @@ -29,9 +29,9 @@ uint8_t finished=0; //encryption uint8_t encryption=0; -struct AES_ctx ctx; -uint8_t key[AES_KEYLEN]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; //TODO: replace with a `-K` arg key entry -uint8_t iv[AES_BLOCKLEN]; +int type = 1; +uint8_t key[32]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; //TODO: replace with a `-K` arg key entry +uint8_t iv[16]; time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC //main routine @@ -49,7 +49,7 @@ int main(int argc, char* argv[]) if(encryption==2) { //TODO: read key - AES_init_ctx(&ctx, key); + *((int32_t*)&iv[0])=(uint32_t)time(NULL)-(uint32_t)epoch; //timestamp for(uint8_t i=4; i<4+10; i++) iv[i]=0; //10 random bytes TODO: replace with a rand() or pass through an additional arg } @@ -116,8 +116,7 @@ int main(int argc, char* argv[]) if(encryption==2) { *((uint16_t*)&iv[14])=fn; - AES_ctx_set_iv(&ctx, iv); //re-init IV (update FN) - AES_CTR_xcrypt_buffer(&ctx, data, AES_BLOCKLEN); + aes_ctr_bytewise_payload_crypt(iv, key, data, type); } //encode the rest of the frame (starting at bit 96 - 0..95 are filled with LICH) diff --git a/tiny-AES-c b/tiny-AES-c deleted file mode 160000 index f06ac37..0000000 --- a/tiny-AES-c +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f06ac37fc31dfdaca2e0d9bec83f90d5663c319b From 56663b198dc9b1cf57b290b0ecea40e9335c5cee Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sun, 16 Jun 2024 12:25:25 -0400 Subject: [PATCH 09/33] Add Submodule Correctly? --- tinier-aes | 1 + 1 file changed, 1 insertion(+) create mode 160000 tinier-aes diff --git a/tinier-aes b/tinier-aes new file mode 160000 index 0000000..a15f518 --- /dev/null +++ b/tinier-aes @@ -0,0 +1 @@ +Subproject commit a15f5186a7b344ef8a783ba3118e7407d3cd22c8 From 6deee453e890992977792ffcc0fc2e6ffa059943 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sun, 16 Jun 2024 20:23:07 -0400 Subject: [PATCH 10/33] Add Debug m17-coder-sym for debugging AES Encryption to Float Output to be decrypted by M17-FME (Working!); --- .gitignore | 1 + SP5WWP/m17-coder/Makefile | 7 +- SP5WWP/m17-coder/m17-coder-sym-debug.c | 276 +++++++++++++++++++++++++ 3 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 SP5WWP/m17-coder/m17-coder-sym-debug.c diff --git a/.gitignore b/.gitignore index d1ad3d8..82dd2c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /SP5WWP/grc/*.py /SP5WWP/m17-coder/m17-coder-sym +/SP5WWP/m17-coder/m17-coder-sym-debug /SP5WWP/m17-decoder/m17-decoder-sym /SP5WWP/m17-packet/m17-packet-encode /SP5WWP/m17-packet/m17-packet-decode diff --git a/SP5WWP/m17-coder/Makefile b/SP5WWP/m17-coder/Makefile index e6e6d5f..779527f 100644 --- a/SP5WWP/m17-coder/Makefile +++ b/SP5WWP/m17-coder/Makefile @@ -1,5 +1,10 @@ +all: m17-coder-sym m17-coder-sym-debug + m17-coder-sym: m17-coder-sym.c gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym.c -o m17-coder-sym -lm -lm17 +m17-coder-sym-debug: m17-coder-sym-debug.c + gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym-debug.c -o m17-coder-sym-debug -lm -lm17 + clean: - rm -f m17-coder-sym + rm -f m17-coder-sym m17-coder-sym-debug diff --git a/SP5WWP/m17-coder/m17-coder-sym-debug.c b/SP5WWP/m17-coder/m17-coder-sym-debug.c new file mode 100644 index 0000000..c2eafb3 --- /dev/null +++ b/SP5WWP/m17-coder/m17-coder-sym-debug.c @@ -0,0 +1,276 @@ +#include +#include +#include +#include +#include + +//libm17 +#include +//tinier-aes +#include "../../tinier-aes/aes.c" + +//#define FN60_DEBUG + +struct LSF lsf, next_lsf; + +uint8_t lich[6]; //48 bits packed raw, unencoded LICH +uint8_t lich_encoded[12]; //96 bits packed, encoded LICH +uint8_t enc_bits[SYM_PER_PLD*2]; //type-2 bits, unpacked +uint8_t rf_bits[SYM_PER_PLD*2]; //type-4 bits, unpacked + +float frame_buff[192]; +uint32_t frame_buff_cnt; + +uint8_t data[16], next_data[16]; //raw payload, packed bits +uint16_t fn=0; //16-bit Frame Number (for the stream mode) +uint8_t lich_cnt=0; //0..5 LICH counter +uint8_t got_lsf=0; //have we filled the LSF struct yet? +uint8_t finished=0; + +//encryption + +uint8_t encryption=0; +int type = 1; //1=AES128, 2=AES192, 3=AES256 + +uint8_t key[32]; //TODO: replace with a `-K` arg key entry +uint8_t iv[16]; + +time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC + +//main routine +int main(int argc, char* argv[]) +{ + //debug + //printf("%06X\n", golay24_encode(1)); //golay encoder codeword test + //printf("%d -> %d -> %d\n", 1, intrl_seq[1], intrl_seq[intrl_seq[1]]); //interleaver bijective reciprocality test, f(f(x))=x + //return 0; + + //encryption init + if(argc>1 && strstr(argv[1], "-K")) + encryption=2; //AES key was passed + + srand(time(NULL)); //seed random number generator + memset(key, 0, 32*sizeof(uint8_t)); + memset(iv, 0, 16*sizeof(uint8_t)); + + //generate random key + // for (uint8_t i = 0; i < 32; i++) + // key[i] = rand() & 0xFF; + + //hard coded key + for (uint8_t i = 0; i < 32; i++) + key[i] = 0x77; + + //print the random key + fprintf (stderr, "\nAES Key:"); + for (uint8_t i = 0; i < 32; i++) + { + if (i == 16) + fprintf (stderr, "\n "); + fprintf (stderr, " %02X", key[i]); + } + fprintf (stderr, "\n"); + + if(encryption==2) + { + //TODO: read user input key + + // *((int32_t*)&iv[0])=(uint32_t)time(NULL)-(uint32_t)epoch; //timestamp //note: I don't think this works as intended + for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); + for(uint8_t i=4; i<4+10; i++) iv[i] = rand() & 0xFF; //10 random bytes + } + + memset(next_lsf.dst, 0xFF, 6*sizeof(uint8_t)); //broadcast + + //AB1CDE + next_lsf.src[0] = 0x00; + next_lsf.src[1] = 0x00; + next_lsf.src[2] = 0x1F; + next_lsf.src[3] = 0x24; + next_lsf.src[4] = 0x5D; + next_lsf.src[5] = 0x51; + + if (encryption == 2) //AES ENC, 3200 voice + { + next_lsf.type[0] = 0x03; + next_lsf.type[1] = 0x95; + } + else //no enc or enc_st field, normal 3200 voice + { + next_lsf.type[0] = 0x00; + next_lsf.type[1] = 0x05; + } + + finished = 0; + + if (encryption == 2) + { + memcpy(&(next_lsf.meta), iv, 14); //AES encryption enabled - use 112 bits of IV + } + else //scrambler, or clear + { + memset(next_lsf.meta, 0, 14*sizeof(uint8_t)); + } + + // while(!finished) + for (uint8_t z = 0; z < 31; z++) //just crank out 5 superframes + { + if(lich_cnt == 0) + { + lsf = next_lsf; + + //calculate LSF CRC + uint16_t ccrc=LSF_CRC(&lsf); + lsf.crc[0]=ccrc>>8; + lsf.crc[1]=ccrc&0xFF; + } + + memset(next_data, 0, sizeof(next_data)); + memcpy(data, next_data, sizeof(data)); + + if (encryption==2) //AES encryption enabled - use 112 bits of IV + { + memcpy(&(next_lsf.meta), iv, 14); + iv[14] = (fn >> 8) & 0xFF; + iv[15] = (fn >> 0) & 0xFF; + } + else //Scrambler, or Clear + { + memset(next_lsf.meta, 0, 14*sizeof(uint8_t)); + } + + if(got_lsf) //stream frames + { + //send stream frame syncword + frame_buff_cnt=0; + send_syncword(frame_buff, &frame_buff_cnt, SYNC_STR); + + //extract LICH from the whole LSF + extract_LICH(lich, lich_cnt, &lsf); + + //encode the LICH + encode_LICH(lich_encoded, lich); + + //unpack LICH (12 bytes) + unpack_LICH(enc_bits, lich_encoded); + + //encrypt + if(encryption==2) + { + fprintf(stderr, "FN: %03d; IV: ", fn); + for(uint8_t i=0; i<16; i++) + fprintf(stderr, "%02X", iv[i]); + fprintf(stderr, "\n"); + + fprintf(stderr, "\t IN: "); + for(uint8_t i=0; i<16; i++) + fprintf(stderr, "%02X", data[i]); + fprintf(stderr, "\n"); + + aes_ctr_bytewise_payload_crypt(iv, key, data, type); + + fprintf(stderr, "\tOUT: "); + for(uint8_t i=0; i<16; i++) + fprintf(stderr, "%02X", data[i]); + fprintf(stderr, "\n"); + } + + //encode the rest of the frame (starting at bit 96 - 0..95 are filled with LICH) + conv_encode_stream_frame(&enc_bits[96], data, finished ? (fn | 0x8000) : fn); + + //reorder bits + reorder_bits(rf_bits, enc_bits); + + //randomize + randomize_bits(rf_bits); + + //send dummy symbols (debug) + /*float s=0.0; + for(uint8_t i=0; i float.sym +//decode debug with -- m17-fme -r -f float.sym -v 1 -E '7777777777777777 7777777777777777 7777777777777777 7777777777777777' \ No newline at end of file From 652f219f1da26e01aff49a3d6326ae35c7768c64 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sun, 16 Jun 2024 21:26:17 -0400 Subject: [PATCH 11/33] Add Scrambler Mode to m17-coder-sym-debug; --- SP5WWP/m17-coder/m17-coder-sym-debug.c | 146 +++++++++++++++++++++---- 1 file changed, 124 insertions(+), 22 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym-debug.c b/SP5WWP/m17-coder/m17-coder-sym-debug.c index c2eafb3..9e105d1 100644 --- a/SP5WWP/m17-coder/m17-coder-sym-debug.c +++ b/SP5WWP/m17-coder/m17-coder-sym-debug.c @@ -28,15 +28,75 @@ uint8_t got_lsf=0; //have we filled the LSF struct yet? uint8_t finished=0; //encryption - uint8_t encryption=0; -int type = 1; //1=AES128, 2=AES192, 3=AES256 +int aes_type = 1; //1=AES128, 2=AES192, 3=AES256 +//AES uint8_t key[32]; //TODO: replace with a `-K` arg key entry uint8_t iv[16]; time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC +//Scrambler +uint8_t scr_bytes[96]; +uint8_t scrambler_pn[768]; +uint32_t scrambler_key=0; +uint32_t byte_counter=0; + +//scrambler pn sequence generation +void pn_sequence_generator () +{ + int i = 0; + uint32_t lfsr, bit; + uint8_t subtype = 0; + lfsr = scrambler_key; + + if (lfsr > 0 && lfsr <= 0xFF) subtype = 0; // 8-bit key + else if (lfsr > 0xFF && lfsr <= 0xFFFF) subtype = 1; //16-bit key + else if (lfsr > 0xFFFF && lfsr <= 0xFFFFFF) subtype = 2; //24-bit key + else subtype = 0; // 8-bit key (default) + + //TODO: Set Frame Type based on subtype value + + fprintf (stderr, "\nScrambler Key: %X; Subtype: %d;", lfsr, subtype); + fprintf (stderr, "\n pN: "); //debug + + //run pN sequence with taps specified + for (i = 0; i < 128*6; i++) + { + //get feedback bit with specidifed taps, depending on the subtype + if (subtype == 0) + bit = (lfsr >> 7) ^ (lfsr >> 5) ^ (lfsr >> 4) ^ (lfsr >> 3); + else if (subtype == 1) + bit = (lfsr >> 15) ^ (lfsr >> 14) ^ (lfsr >> 12) ^ (lfsr >> 3); + else if (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; //trancate lfsr to 24-bit (really doesn't matter) + scrambler_pn[i] = lfsr & 1; + + //debug + // if ((i != 0) && (i%64 == 0) ) fprintf (stderr, " \n "); + // fprintf (stderr, "%d", scrambler_pn[i]); + + } + + //pack bit array into byte array for easy data XOR + pack_bit_array_into_byte_array(scrambler_pn, scr_bytes, 96); + + //debug packed bytes + for (i = 0; i < 96; i++) + { + if ((i != 0) && (i%16 == 0) ) fprintf (stderr, " \n "); + fprintf (stderr, " %02X", scr_bytes[i]); + } + + fprintf (stderr, "\n"); +} + //main routine int main(int argc, char* argv[]) { @@ -49,31 +109,38 @@ int main(int argc, char* argv[]) if(argc>1 && strstr(argv[1], "-K")) encryption=2; //AES key was passed + if(argc>1 && strstr(argv[1], "-k")) + { + // scrambler_key = atoi(argv[2]); //would prefer to get the hex input, but good enough to test with + scrambler_key = 0x123456; + encryption=1; //Scrambler key was passed + } + srand(time(NULL)); //seed random number generator memset(key, 0, 32*sizeof(uint8_t)); memset(iv, 0, 16*sizeof(uint8_t)); - //generate random key - // for (uint8_t i = 0; i < 32; i++) - // key[i] = rand() & 0xFF; - - //hard coded key - for (uint8_t i = 0; i < 32; i++) - key[i] = 0x77; - - //print the random key - fprintf (stderr, "\nAES Key:"); - for (uint8_t i = 0; i < 32; i++) - { - if (i == 16) - fprintf (stderr, "\n "); - fprintf (stderr, " %02X", key[i]); - } - fprintf (stderr, "\n"); - if(encryption==2) { //TODO: read user input key + + //generate random key + // for (uint8_t i = 0; i < 32; i++) + // key[i] = rand() & 0xFF; + + //hard coded key + for (uint8_t i = 0; i < 32; i++) + key[i] = 0x77; + + //print the random key + fprintf (stderr, "\nAES Key:"); + for (uint8_t i = 0; i < 32; i++) + { + if (i == 16) + fprintf (stderr, "\n "); + fprintf (stderr, " %02X", key[i]); + } + fprintf (stderr, "\n"); // *((int32_t*)&iv[0])=(uint32_t)time(NULL)-(uint32_t)epoch; //timestamp //note: I don't think this works as intended for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); @@ -95,6 +162,12 @@ int main(int argc, char* argv[]) next_lsf.type[0] = 0x03; next_lsf.type[1] = 0x95; } + else if (encryption == 1) + { + pn_sequence_generator(); + next_lsf.type[0] = 0x03; + next_lsf.type[1] = 0xCD; + } else //no enc or enc_st field, normal 3200 voice { next_lsf.type[0] = 0x00; @@ -167,13 +240,34 @@ int main(int argc, char* argv[]) fprintf(stderr, "%02X", data[i]); fprintf(stderr, "\n"); - aes_ctr_bytewise_payload_crypt(iv, key, data, type); + aes_ctr_bytewise_payload_crypt(iv, key, data, aes_type); fprintf(stderr, "\tOUT: "); for(uint8_t i=0; i<16; i++) fprintf(stderr, "%02X", data[i]); fprintf(stderr, "\n"); } + else if (encryption == 1) + { + fprintf(stderr, "FN: %03d; ", fn); + + fprintf(stderr, "IN: "); + for(uint8_t i=0; i<16; i++) + fprintf(stderr, "%02X", data[i]); + fprintf(stderr, "\n"); + + for(uint8_t i=0; i<16; i++) + { + data[i] ^= scr_bytes[byte_counter%96]; + byte_counter++; + } + + fprintf(stderr, " "); + fprintf(stderr, "\tOUT: "); + for(uint8_t i=0; i<16; i++) + fprintf(stderr, "%02X", data[i]); + fprintf(stderr, "\n"); + } //encode the rest of the frame (starting at bit 96 - 0..95 are filled with LICH) conv_encode_stream_frame(&enc_bits[96], data, finished ? (fn | 0x8000) : fn); @@ -204,6 +298,9 @@ int main(int argc, char* argv[]) //increment the LICH counter lich_cnt = (lich_cnt + 1) % 6; + //reset byte_counter + if (byte_counter == 96) byte_counter = 0; + //debug-only #ifdef FN60_DEBUG if(fn==6*10) @@ -272,5 +369,10 @@ int main(int argc, char* argv[]) return 0; } +//AES //encode debug with -- ./m17-coder-sym-debug -K > float.sym -//decode debug with -- m17-fme -r -f float.sym -v 1 -E '7777777777777777 7777777777777777 7777777777777777 7777777777777777' \ No newline at end of file +//decode debug with -- m17-fme -r -f float.sym -v 1 -E '7777777777777777 7777777777777777 7777777777777777 7777777777777777' + +//Scrambler +//encode debug with -- ./m17-coder-sym-debug -k > scr.sym +//decode debug with -- m17-fme -r -f scr.sym -v 1 -e 123456 \ No newline at end of file From 855918529fe99a802a667f5f9b24a0fc4a685000 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 17 Jun 2024 07:36:40 -0400 Subject: [PATCH 12/33] Misc Output Tweaks on coder-sym-debug; Fix IV Loading on coder-sym. --- SP5WWP/m17-coder/m17-coder-sym-debug.c | 15 +++++++-------- SP5WWP/m17-coder/m17-coder-sym.c | 19 ++++++++++++++----- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym-debug.c b/SP5WWP/m17-coder/m17-coder-sym-debug.c index 9e105d1..93710ec 100644 --- a/SP5WWP/m17-coder/m17-coder-sym-debug.c +++ b/SP5WWP/m17-coder/m17-coder-sym-debug.c @@ -204,7 +204,7 @@ int main(int argc, char* argv[]) if (encryption==2) //AES encryption enabled - use 112 bits of IV { memcpy(&(next_lsf.meta), iv, 14); - iv[14] = (fn >> 8) & 0xFF; + iv[14] = (fn >> 8) & 0x7F; iv[15] = (fn >> 0) & 0xFF; } else //Scrambler, or Clear @@ -230,27 +230,26 @@ int main(int argc, char* argv[]) //encrypt if(encryption==2) { - fprintf(stderr, "FN: %03d; IV: ", fn); + fprintf(stderr, "FN: %04X; IV: ", fn); for(uint8_t i=0; i<16; i++) fprintf(stderr, "%02X", iv[i]); fprintf(stderr, "\n"); - fprintf(stderr, "\t IN: "); + fprintf(stderr, "\t IN: "); for(uint8_t i=0; i<16; i++) fprintf(stderr, "%02X", data[i]); fprintf(stderr, "\n"); aes_ctr_bytewise_payload_crypt(iv, key, data, aes_type); - fprintf(stderr, "\tOUT: "); + fprintf(stderr, "\t OUT: "); for(uint8_t i=0; i<16; i++) fprintf(stderr, "%02X", data[i]); fprintf(stderr, "\n"); } else if (encryption == 1) { - fprintf(stderr, "FN: %03d; ", fn); - + fprintf(stderr, "FN: %04X; ", fn); fprintf(stderr, "IN: "); for(uint8_t i=0; i<16; i++) fprintf(stderr, "%02X", data[i]); @@ -262,8 +261,8 @@ int main(int argc, char* argv[]) byte_counter++; } - fprintf(stderr, " "); - fprintf(stderr, "\tOUT: "); + fprintf(stderr, " "); + fprintf(stderr, "OUT: "); for(uint8_t i=0; i<16; i++) fprintf(stderr, "%02X", data[i]); fprintf(stderr, "\n"); diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index ab3520e..e6745fe 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -29,7 +29,7 @@ uint8_t finished=0; //encryption uint8_t encryption=0; -int type = 1; +int aes_type = 1; //1=AES128, 2=AES192, 3=AES256 uint8_t key[32]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; //TODO: replace with a `-K` arg key entry uint8_t iv[16]; time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC @@ -42,6 +42,10 @@ int main(int argc, char* argv[]) //printf("%d -> %d -> %d\n", 1, intrl_seq[1], intrl_seq[intrl_seq[1]]); //interleaver bijective reciprocality test, f(f(x))=x //return 0; + srand(time(NULL)); //seed random number generator + // memset(key, 0, 32*sizeof(uint8_t)); + memset(iv, 0, 16*sizeof(uint8_t)); + //encryption init if(argc>2 && strstr(argv[1], "-K")) encryption=2; //AES key was passed @@ -50,8 +54,9 @@ int main(int argc, char* argv[]) { //TODO: read key - *((int32_t*)&iv[0])=(uint32_t)time(NULL)-(uint32_t)epoch; //timestamp - for(uint8_t i=4; i<4+10; i++) iv[i]=0; //10 random bytes TODO: replace with a rand() or pass through an additional arg + // *((int32_t*)&iv[0])=(uint32_t)time(NULL)-(uint32_t)epoch; //timestamp + for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); + for(uint8_t i=4; i<4+10; i++) iv[i] = rand() & 0xFF; //10 random bytes } if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; @@ -93,6 +98,8 @@ int main(int argc, char* argv[]) else { memcpy(&(next_lsf.meta), iv, 14); //AES encryption enabled - use 112 bits of IV + iv[14] = (fn >> 8) & 0x7F; + iv[15] = (fn >> 0) & 0xFF; finished=1; } if(fread(next_data, 16, 1, stdin)<1) finished=1; @@ -115,8 +122,10 @@ int main(int argc, char* argv[]) //encrypt if(encryption==2) { - *((uint16_t*)&iv[14])=fn; - aes_ctr_bytewise_payload_crypt(iv, key, data, type); + // *((uint16_t*)&iv[14])=fn; + iv[14] = (fn >> 8) & 0x7F; + iv[15] = (fn >> 0) & 0xFF; + aes_ctr_bytewise_payload_crypt(iv, key, data, aes_type); } //encode the rest of the frame (starting at bit 96 - 0..95 are filled with LICH) From 9c2861af7794637e10aaacc917c1d2953164161d Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 17 Jun 2024 08:49:33 -0400 Subject: [PATCH 13/33] coder-sym: Fix IV loading to include byte that wasn't loading properly; --- SP5WWP/m17-coder/m17-coder-sym-debug.c | 4 ++-- SP5WWP/m17-coder/m17-coder-sym.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym-debug.c b/SP5WWP/m17-coder/m17-coder-sym-debug.c index 93710ec..71e65a8 100644 --- a/SP5WWP/m17-coder/m17-coder-sym-debug.c +++ b/SP5WWP/m17-coder/m17-coder-sym-debug.c @@ -143,8 +143,8 @@ int main(int argc, char* argv[]) fprintf (stderr, "\n"); // *((int32_t*)&iv[0])=(uint32_t)time(NULL)-(uint32_t)epoch; //timestamp //note: I don't think this works as intended - for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); - for(uint8_t i=4; i<4+10; i++) iv[i] = rand() & 0xFF; //10 random bytes + for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); + for(uint8_t i=3; i<14; i++) iv[i] = rand() & 0xFF; //10 random bytes } memset(next_lsf.dst, 0xFF, 6*sizeof(uint8_t)); //broadcast diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index e6745fe..9d4882f 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -55,8 +55,8 @@ int main(int argc, char* argv[]) //TODO: read key // *((int32_t*)&iv[0])=(uint32_t)time(NULL)-(uint32_t)epoch; //timestamp - for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); - for(uint8_t i=4; i<4+10; i++) iv[i] = rand() & 0xFF; //10 random bytes + for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); + for(uint8_t i=3; i<14; i++) iv[i] = rand() & 0xFF; //10 random bytes } if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; From 53213a30661da9c82272ba6b84bf4d9babe93d0d Mon Sep 17 00:00:00 2001 From: Wojciech Kaczmarski <44336093+sp5wwp@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:58:29 +0200 Subject: [PATCH 14/33] streamer .grc update --- SP5WWP/grc/m17_streamer.grc | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/SP5WWP/grc/m17_streamer.grc b/SP5WWP/grc/m17_streamer.grc index 1c8a52e..2392333 100644 --- a/SP5WWP/grc/m17_streamer.grc +++ b/SP5WWP/grc/m17_streamer.grc @@ -1,11 +1,11 @@ options: parameters: - author: SP5WWP + author: Wojciech Kaczmarski SP5WWP catch_exceptions: 'True' category: '[GRC Hier Blocks]' cmake_opt: '' comment: '' - copyright: M17 Project, Dec 2022 + copyright: M17 Project, Jun 2024 description: '' gen_cmake: 'On' gen_linking: dynamic @@ -38,9 +38,9 @@ blocks: parameters: affinity: '' alias: '' - append: 'True' + append: 'False' comment: '' - file: /tmp/fifo1 + file: ../stream_fifo type: byte unbuffered: 'False' vlen: '1' @@ -48,7 +48,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [680, 172.0] + coordinate: [696, 172.0] rotation: 0 state: true - name: blocks_stream_mux_0 @@ -70,25 +70,27 @@ blocks: coordinate: [360, 128.0] rotation: 0 state: enabled -- name: blocks_throttle_0 - id: blocks_throttle +- name: blocks_throttle2_0 + id: blocks_throttle2 parameters: affinity: '' alias: '' comment: '' ignoretag: 'True' + limit: auto + maximum: '0.1' maxoutbuf: '0' minoutbuf: '0' - samples_per_second: (6+6+2+14+16)*8*(1000/40) + samples_per_second: (6+6+2+14+16)*(1000/40) type: byte vlen: '1' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [528, 188.0] + coordinate: [536, 180.0] rotation: 0 - state: enabled + state: true - name: blocks_vector_source_x_0 id: blocks_vector_source_x parameters: @@ -258,8 +260,8 @@ blocks: state: true connections: -- [blocks_stream_mux_0, '0', blocks_throttle_0, '0'] -- [blocks_throttle_0, '0', blocks_file_sink_0, '0'] +- [blocks_stream_mux_0, '0', blocks_throttle2_0, '0'] +- [blocks_throttle2_0, '0', blocks_file_sink_0, '0'] - [blocks_vector_source_x_0, '0', blocks_stream_mux_0, '0'] - [blocks_vector_source_x_0_0, '0', blocks_stream_mux_0, '1'] - [blocks_vector_source_x_0_1, '0', blocks_stream_mux_0, '2'] @@ -268,3 +270,4 @@ connections: metadata: file_format: 1 + grc_version: 3.10.7.0 From f240f76a790be1dbbd572c9ef2e3ea463a3b1e9f Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 17 Jun 2024 12:19:35 -0400 Subject: [PATCH 15/33] Add Scrambler Mode to m17-coder-sym.c; Need to Test Enc Modes in the flowgraph; --- SP5WWP/m17-coder/m17-coder-sym-debug.c | 10 ++-- SP5WWP/m17-coder/m17-coder-sym.c | 83 ++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym-debug.c b/SP5WWP/m17-coder/m17-coder-sym-debug.c index 71e65a8..1d8cb86 100644 --- a/SP5WWP/m17-coder/m17-coder-sym-debug.c +++ b/SP5WWP/m17-coder/m17-coder-sym-debug.c @@ -105,6 +105,10 @@ int main(int argc, char* argv[]) //printf("%d -> %d -> %d\n", 1, intrl_seq[1], intrl_seq[intrl_seq[1]]); //interleaver bijective reciprocality test, f(f(x))=x //return 0; + srand(time(NULL)); //seed random number generator + memset(key, 0, 32*sizeof(uint8_t)); + memset(iv, 0, 16*sizeof(uint8_t)); + //encryption init if(argc>1 && strstr(argv[1], "-K")) encryption=2; //AES key was passed @@ -114,11 +118,7 @@ int main(int argc, char* argv[]) // scrambler_key = atoi(argv[2]); //would prefer to get the hex input, but good enough to test with scrambler_key = 0x123456; encryption=1; //Scrambler key was passed - } - - srand(time(NULL)); //seed random number generator - memset(key, 0, 32*sizeof(uint8_t)); - memset(iv, 0, 16*sizeof(uint8_t)); + } if(encryption==2) { diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 9d4882f..3344d5c 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -27,6 +27,10 @@ uint8_t lich_cnt=0; //0..5 LICH counter uint8_t got_lsf=0; //have we filled the LSF struct yet? uint8_t finished=0; + +//TODO: Test Encyrption Modes in Flowgraph to make sure they work the same +//as they do in m17-coder-sym-debug.c + //encryption uint8_t encryption=0; int aes_type = 1; //1=AES128, 2=AES192, 3=AES256 @@ -34,6 +38,66 @@ uint8_t key[32]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, uint8_t iv[16]; time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC +//Scrambler +uint8_t scr_bytes[96]; +uint8_t scrambler_pn[768]; +uint32_t scrambler_key=0; +uint32_t byte_counter=0; + +//scrambler pn sequence generation +void pn_sequence_generator () +{ + int i = 0; + uint32_t lfsr, bit; + uint8_t subtype = 0; + lfsr = scrambler_key; + + if (lfsr > 0 && lfsr <= 0xFF) subtype = 0; // 8-bit key + else if (lfsr > 0xFF && lfsr <= 0xFFFF) subtype = 1; //16-bit key + else if (lfsr > 0xFFFF && lfsr <= 0xFFFFFF) subtype = 2; //24-bit key + else subtype = 0; // 8-bit key (default) + + //TODO: Set Frame Type based on subtype value + + fprintf (stderr, "\nScrambler Key: %X; Subtype: %d;", lfsr, subtype); + fprintf (stderr, "\n pN: "); //debug + + //run pN sequence with taps specified + for (i = 0; i < 128*6; i++) + { + //get feedback bit with specidifed taps, depending on the subtype + if (subtype == 0) + bit = (lfsr >> 7) ^ (lfsr >> 5) ^ (lfsr >> 4) ^ (lfsr >> 3); + else if (subtype == 1) + bit = (lfsr >> 15) ^ (lfsr >> 14) ^ (lfsr >> 12) ^ (lfsr >> 3); + else if (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; //trancate lfsr to 24-bit (really doesn't matter) + scrambler_pn[i] = lfsr & 1; + + //debug + // if ((i != 0) && (i%64 == 0) ) fprintf (stderr, " \n "); + // fprintf (stderr, "%d", scrambler_pn[i]); + + } + + //pack bit array into byte array for easy data XOR + pack_bit_array_into_byte_array(scrambler_pn, scr_bytes, 96); + + //debug packed bytes + for (i = 0; i < 96; i++) + { + if ((i != 0) && (i%16 == 0) ) fprintf (stderr, " \n "); + fprintf (stderr, " %02X", scr_bytes[i]); + } + + fprintf (stderr, "\n"); +} + //main routine int main(int argc, char* argv[]) { @@ -50,6 +114,13 @@ int main(int argc, char* argv[]) if(argc>2 && strstr(argv[1], "-K")) encryption=2; //AES key was passed + if(argc>1 && strstr(argv[1], "-k")) + { + // scrambler_key = atoi(argv[2]); //would prefer to get the hex input, but good enough to test with + scrambler_key = 0x123456; + encryption=1; //Scrambler key was passed + } + if(encryption==2) { //TODO: read key @@ -128,6 +199,15 @@ int main(int argc, char* argv[]) aes_ctr_bytewise_payload_crypt(iv, key, data, aes_type); } + else if (encryption == 1) + { + for(uint8_t i=0; i<16; i++) + { + data[i] ^= scr_bytes[byte_counter%96]; + byte_counter++; + } + } + //encode the rest of the frame (starting at bit 96 - 0..95 are filled with LICH) conv_encode_stream_frame(&enc_bits[96], data, finished ? (fn | 0x8000) : fn); @@ -157,6 +237,9 @@ int main(int argc, char* argv[]) //increment the LICH counter lich_cnt = (lich_cnt + 1) % 6; + //reset byte_counter + if (byte_counter == 96) byte_counter = 0; + //debug-only #ifdef FN60_DEBUG if(fn==6*10) From f28c1ae6ee8defb4b6198169ddd42ad7bec36e3f Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 17 Jun 2024 14:23:07 -0400 Subject: [PATCH 16/33] Fixes to m17-coder-sym to get enc to work when using flowgraph; --- SP5WWP/m17-coder/m17-coder-sym.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 3344d5c..0644a5b 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -28,13 +28,13 @@ uint8_t got_lsf=0; //have we filled the LSF struct yet? uint8_t finished=0; -//TODO: Test Encyrption Modes in Flowgraph to make sure they work the same -//as they do in m17-coder-sym-debug.c +//TODO: Make Encyrption Mode Vectors (key, frametype) in Flowgraph for fread? +//or make user args for those //encryption uint8_t encryption=0; int aes_type = 1; //1=AES128, 2=AES192, 3=AES256 -uint8_t key[32]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; //TODO: replace with a `-K` arg key entry +uint8_t key[32]; //TODO: replace with a `-K` arg key entry uint8_t iv[16]; time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC @@ -107,18 +107,25 @@ int main(int argc, char* argv[]) //return 0; srand(time(NULL)); //seed random number generator - // memset(key, 0, 32*sizeof(uint8_t)); + memset(key, 0, 32*sizeof(uint8_t)); memset(iv, 0, 16*sizeof(uint8_t)); //encryption init - if(argc>2 && strstr(argv[1], "-K")) + if(argc>1 && strstr(argv[1], "-K")) + { + //hard coded key + for (uint8_t i = 0; i < 32; i++) + key[i] = 0x77; + encryption=2; //AES key was passed + } if(argc>1 && strstr(argv[1], "-k")) { // scrambler_key = atoi(argv[2]); //would prefer to get the hex input, but good enough to test with scrambler_key = 0x123456; encryption=1; //Scrambler key was passed + pn_sequence_generator(); } if(encryption==2) @@ -133,14 +140,15 @@ int main(int argc, char* argv[]) if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //this needs to be read in regardless with the current setup on m17_streamer.grc if(encryption==0) { - if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //read data from stdin + // if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //read data from stdin } else { memcpy(&(next_lsf.meta), iv, 14); //AES encryption enabled - use 112 bits of IV - finished=1; + // finished=1; //this was blocking previously } if(fread(next_data, 16, 1, stdin)<1) finished=1; @@ -162,16 +170,17 @@ int main(int argc, char* argv[]) if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //read data from stdin if(encryption==0) { - if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //read data from stdin + // if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //read data from stdin } else { memcpy(&(next_lsf.meta), iv, 14); //AES encryption enabled - use 112 bits of IV iv[14] = (fn >> 8) & 0x7F; iv[15] = (fn >> 0) & 0xFF; - finished=1; + // finished=1; //this was blocking previously } if(fread(next_data, 16, 1, stdin)<1) finished=1; From 180d2e18358e385a91c26bc57d7aa6cf4428c962 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 19 Jun 2024 06:22:02 -0400 Subject: [PATCH 17/33] Cleanup Some Code; --- SP5WWP/m17-coder/m17-coder-sym.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 0644a5b..4172a3e 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -131,8 +131,6 @@ int main(int argc, char* argv[]) if(encryption==2) { //TODO: read key - - // *((int32_t*)&iv[0])=(uint32_t)time(NULL)-(uint32_t)epoch; //timestamp for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); for(uint8_t i=3; i<14; i++) iv[i] = rand() & 0xFF; //10 random bytes } @@ -140,16 +138,7 @@ int main(int argc, char* argv[]) if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //this needs to be read in regardless with the current setup on m17_streamer.grc - if(encryption==0) - { - // if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //read data from stdin - } - else - { - memcpy(&(next_lsf.meta), iv, 14); //AES encryption enabled - use 112 bits of IV - // finished=1; //this was blocking previously - } + if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; if(fread(next_data, 16, 1, stdin)<1) finished=1; while(!finished) @@ -170,18 +159,16 @@ int main(int argc, char* argv[]) if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //read data from stdin - if(encryption==0) + if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; + + //AES encryption enabled - use 112 bits of IV + if(encryption==2) { - // if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; //read data from stdin - } - else - { - memcpy(&(next_lsf.meta), iv, 14); //AES encryption enabled - use 112 bits of IV + memcpy(&(next_lsf.meta), iv, 14); iv[14] = (fn >> 8) & 0x7F; iv[15] = (fn >> 0) & 0xFF; - // finished=1; //this was blocking previously } + if(fread(next_data, 16, 1, stdin)<1) finished=1; if(got_lsf) //stream frames @@ -202,7 +189,6 @@ int main(int argc, char* argv[]) //encrypt if(encryption==2) { - // *((uint16_t*)&iv[14])=fn; iv[14] = (fn >> 8) & 0x7F; iv[15] = (fn >> 0) & 0xFF; aes_ctr_bytewise_payload_crypt(iv, key, data, aes_type); From e42d4cf90a93fb2235565ecafd6dcf3f1ddfbe63 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 19 Jun 2024 07:15:06 -0400 Subject: [PATCH 18/33] Rework Scrambler Mode to use constantly perpetuating SEED value; Consolidate m17-coder-sym-debug code into m17-coder-sym (eliminate duplicate code); --- SP5WWP/m17-coder/m17-coder-sym.c | 177 +++++++++++++++++++++++-------- 1 file changed, 133 insertions(+), 44 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 4172a3e..019f114 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -9,8 +9,6 @@ //tinier-aes #include "../../tinier-aes/aes.c" -//#define FN60_DEBUG - struct LSF lsf, next_lsf; uint8_t lich[6]; //48 bits packed raw, unencoded LICH @@ -39,10 +37,13 @@ uint8_t iv[16]; time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC //Scrambler -uint8_t scr_bytes[96]; -uint8_t scrambler_pn[768]; +uint8_t scr_bytes[16]; +uint8_t scrambler_pn[128]; uint32_t scrambler_key=0; -uint32_t byte_counter=0; +uint32_t scrambler_seed=0; + +//debug mode (preset lsf, zero payload for enc testing, etc) +uint8_t debug_mode=0; //scrambler pn sequence generation void pn_sequence_generator () @@ -50,7 +51,7 @@ void pn_sequence_generator () int i = 0; uint32_t lfsr, bit; uint8_t subtype = 0; - lfsr = scrambler_key; + lfsr = scrambler_seed; if (lfsr > 0 && lfsr <= 0xFF) subtype = 0; // 8-bit key else if (lfsr > 0xFF && lfsr <= 0xFFFF) subtype = 1; //16-bit key @@ -58,12 +59,14 @@ void pn_sequence_generator () else subtype = 0; // 8-bit key (default) //TODO: Set Frame Type based on subtype value - - fprintf (stderr, "\nScrambler Key: %X; Subtype: %d;", lfsr, subtype); - fprintf (stderr, "\n pN: "); //debug + if (debug_mode == 1) + { + fprintf (stderr, "\nScrambler Key: %X; Seed: %X; Subtype: %d;", scrambler_key, lfsr, subtype); + fprintf (stderr, "\n pN: "); //debug + } //run pN sequence with taps specified - for (i = 0; i < 128*6; i++) + for (i = 0; i < 128; i++) { //get feedback bit with specidifed taps, depending on the subtype if (subtype == 0) @@ -79,23 +82,28 @@ void pn_sequence_generator () lfsr &= 0xFFFFFF; //trancate lfsr to 24-bit (really doesn't matter) scrambler_pn[i] = lfsr & 1; - //debug - // if ((i != 0) && (i%64 == 0) ) fprintf (stderr, " \n "); - // fprintf (stderr, "%d", scrambler_pn[i]); - } //pack bit array into byte array for easy data XOR - pack_bit_array_into_byte_array(scrambler_pn, scr_bytes, 96); + pack_bit_array_into_byte_array(scrambler_pn, scr_bytes, 16); - //debug packed bytes - for (i = 0; i < 96; i++) + //save scrambler seed for next round + scrambler_seed = lfsr; + + //truncate seed so subtype will continue to set properly on subsequent passes + if (subtype == 0) scrambler_seed &= 0xFF; + if (subtype == 1) scrambler_seed &= 0xFFFF; + if (subtype == 2) scrambler_seed &= 0xFFFFFF; + else scrambler_seed &= 0xFF; + + if (debug_mode == 1) { - if ((i != 0) && (i%16 == 0) ) fprintf (stderr, " \n "); - fprintf (stderr, " %02X", scr_bytes[i]); + //debug packed bytes + for (i = 0; i < 16; i++) + fprintf (stderr, " %02X", scr_bytes[i]); + fprintf (stderr, "\n"); } - - fprintf (stderr, "\n"); + } //main routine @@ -106,10 +114,23 @@ int main(int argc, char* argv[]) //printf("%d -> %d -> %d\n", 1, intrl_seq[1], intrl_seq[intrl_seq[1]]); //interleaver bijective reciprocality test, f(f(x))=x //return 0; + //test only, delete next two lines later + debug_mode = 1; + encryption = 2; + srand(time(NULL)); //seed random number generator memset(key, 0, 32*sizeof(uint8_t)); memset(iv, 0, 16*sizeof(uint8_t)); + //TODO: Redo args so we can get more than one at the same time + //copy and paste from m17-packet-encode + + //debug mode + if(argc>1 && strstr(argv[1], "-D")) + { + debug_mode = 1; + } + //encryption init if(argc>1 && strstr(argv[1], "-K")) { @@ -117,6 +138,18 @@ int main(int argc, char* argv[]) for (uint8_t i = 0; i < 32; i++) key[i] = 0x77; + if (debug_mode == 1) + { + fprintf (stderr, "\nAES Key:"); + for (uint8_t i = 0; i < 32; i++) + { + if (i == 16) + fprintf (stderr, "\n "); + fprintf (stderr, " %02X", key[i]); + } + fprintf (stderr, "\n"); + } + encryption=2; //AES key was passed } @@ -124,22 +157,60 @@ int main(int argc, char* argv[]) { // scrambler_key = atoi(argv[2]); //would prefer to get the hex input, but good enough to test with scrambler_key = 0x123456; + scrambler_seed = scrambler_key; //initialize the seed with the key value encryption=1; //Scrambler key was passed - pn_sequence_generator(); + //pn_sequence_generator(); } if(encryption==2) { //TODO: read key - for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); - for(uint8_t i=3; i<14; i++) iv[i] = rand() & 0xFF; //10 random bytes + for(uint8_t i=0; i<4; i++) + iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); + for(uint8_t i=3; i<14; i++) + iv[i] = rand() & 0xFF; //10 random bytes } - if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; - if(fread(next_data, 16, 1, stdin)<1) finished=1; + if (debug_mode == 1) + { + //broadcast + memset(next_lsf.dst, 0xFF, 6*sizeof(uint8_t)); + + //AB1CDE + next_lsf.src[0] = 0x00; + next_lsf.src[1] = 0x00; + next_lsf.src[2] = 0x1F; + next_lsf.src[3] = 0x24; + next_lsf.src[4] = 0x5D; + next_lsf.src[5] = 0x51; + + if (encryption == 2) //AES ENC, 3200 voice + { + next_lsf.type[0] = 0x03; + next_lsf.type[1] = 0x95; + } + else if (encryption == 1) //Scrambler ENC, 3200 Voice + { + next_lsf.type[0] = 0x03; + next_lsf.type[1] = 0xCD; + } + else //no enc or subtype field, normal 3200 voice + { + next_lsf.type[0] = 0x00; + next_lsf.type[1] = 0x05; + } + + finished = 0; + } + + else + { + if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; + if(fread(next_data, 16, 1, stdin)<1) finished=1; + } while(!finished) { @@ -155,11 +226,20 @@ int main(int argc, char* argv[]) memcpy(data, next_data, sizeof(data)); - //we could discard the data we already have - if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; + if (debug_mode == 1) + { + memset(next_data, 0, sizeof(next_data)); + memcpy(data, next_data, sizeof(data)); + } + + else + { + if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; + if(fread(next_data, 16, 1, stdin)<1) finished=1; + } //AES encryption enabled - use 112 bits of IV if(encryption==2) @@ -169,7 +249,8 @@ int main(int argc, char* argv[]) iv[15] = (fn >> 0) & 0xFF; } - if(fread(next_data, 16, 1, stdin)<1) finished=1; + else if(encryption==1) + pn_sequence_generator(); if(got_lsf) //stream frames { @@ -198,8 +279,7 @@ int main(int argc, char* argv[]) { for(uint8_t i=0; i<16; i++) { - data[i] ^= scr_bytes[byte_counter%96]; - byte_counter++; + data[i] ^= scr_bytes[i]; } } @@ -232,14 +312,13 @@ int main(int argc, char* argv[]) //increment the LICH counter lich_cnt = (lich_cnt + 1) % 6; - //reset byte_counter - if (byte_counter == 96) byte_counter = 0; - //debug-only - #ifdef FN60_DEBUG - if(fn==6*10) - return 0; - #endif + if (debug_mode == 1) + { + if(fn==6*10) + return 0; + } + } else //LSF { @@ -302,3 +381,13 @@ int main(int argc, char* argv[]) return 0; } + +//DEBUG: + +//AES +//encode debug with -- ./m17-coder-sym -K > float.sym +//decode debug with -- m17-fme -r -f float.sym -v 1 -E '7777777777777777 7777777777777777 7777777777777777 7777777777777777' + +//Scrambler +//encode debug with -- ./m17-coder-sym -k > scr.sym +//decode debug with -- m17-fme -r -f scr.sym -v 1 -e 123456 From 9fd6231c90e9d2e12c77d1df295bd080453cd7e3 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 19 Jun 2024 07:38:41 -0400 Subject: [PATCH 19/33] More Scrambler Cleanup and Fixes; --- SP5WWP/m17-coder/m17-coder-sym.c | 50 +++++++++++++++----------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 019f114..3995419 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -25,10 +25,6 @@ uint8_t lich_cnt=0; //0..5 LICH counter uint8_t got_lsf=0; //have we filled the LSF struct yet? uint8_t finished=0; - -//TODO: Make Encyrption Mode Vectors (key, frametype) in Flowgraph for fread? -//or make user args for those - //encryption uint8_t encryption=0; int aes_type = 1; //1=AES128, 2=AES192, 3=AES256 @@ -41,46 +37,51 @@ uint8_t scr_bytes[16]; uint8_t scrambler_pn[128]; uint32_t scrambler_key=0; uint32_t scrambler_seed=0; +int8_t scrambler_subtype = -1; //debug mode (preset lsf, zero payload for enc testing, etc) uint8_t debug_mode=0; //scrambler pn sequence generation -void pn_sequence_generator () +void scrambler_sequence_generator () { int i = 0; uint32_t lfsr, bit; - uint8_t subtype = 0; lfsr = scrambler_seed; - if (lfsr > 0 && lfsr <= 0xFF) subtype = 0; // 8-bit key - else if (lfsr > 0xFF && lfsr <= 0xFFFF) subtype = 1; //16-bit key - else if (lfsr > 0xFFFF && lfsr <= 0xFFFFFF) subtype = 2; //24-bit key - else subtype = 0; // 8-bit key (default) + //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 subtype value + //TODO: Set Frame Type based on scrambler_subtype value if (debug_mode == 1) { - fprintf (stderr, "\nScrambler Key: %X; Seed: %X; Subtype: %d;", scrambler_key, lfsr, subtype); + fprintf (stderr, "\nScrambler Key: %X; Seed: %X; Subtype: %d;", scrambler_key, lfsr, scrambler_subtype); fprintf (stderr, "\n pN: "); //debug } //run pN sequence with taps specified for (i = 0; i < 128; i++) { - //get feedback bit with specidifed taps, depending on the subtype - if (subtype == 0) + //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 (subtype == 1) + else if (scrambler_subtype == 1) bit = (lfsr >> 15) ^ (lfsr >> 14) ^ (lfsr >> 12) ^ (lfsr >> 3); - else if (subtype == 2) + 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; //trancate lfsr to 24-bit (really doesn't matter) - scrambler_pn[i] = lfsr & 1; + lfsr &= 0xFFFFFF; //truncate lfsr to 24-bit (really doesn't matter) + scrambler_pn[i] = bit; } @@ -91,10 +92,10 @@ void pn_sequence_generator () scrambler_seed = lfsr; //truncate seed so subtype will continue to set properly on subsequent passes - if (subtype == 0) scrambler_seed &= 0xFF; - if (subtype == 1) scrambler_seed &= 0xFFFF; - if (subtype == 2) scrambler_seed &= 0xFFFFFF; - else scrambler_seed &= 0xFF; + 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) { @@ -159,7 +160,6 @@ int main(int argc, char* argv[]) scrambler_key = 0x123456; scrambler_seed = scrambler_key; //initialize the seed with the key value encryption=1; //Scrambler key was passed - //pn_sequence_generator(); } if(encryption==2) @@ -249,9 +249,6 @@ int main(int argc, char* argv[]) iv[15] = (fn >> 0) & 0xFF; } - else if(encryption==1) - pn_sequence_generator(); - if(got_lsf) //stream frames { //send stream frame syncword @@ -277,6 +274,7 @@ int main(int argc, char* argv[]) else if (encryption == 1) { + scrambler_sequence_generator(); for(uint8_t i=0; i<16; i++) { data[i] ^= scr_bytes[i]; From ffbe510ddeb949317cad788bb3fab7606e1279f6 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 19 Jun 2024 09:58:09 -0400 Subject: [PATCH 20/33] Add Command Line Scanning (WIP); Seperate Usage From CLI Scan; parse_raw_key_string for key entry reading; --- SP5WWP/m17-coder/m17-coder-sym.c | 171 +++++++++++++++++++++---------- 1 file changed, 118 insertions(+), 53 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 3995419..e940c20 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -27,10 +27,10 @@ uint8_t finished=0; //encryption uint8_t encryption=0; -int aes_type = 1; //1=AES128, 2=AES192, 3=AES256 -uint8_t key[32]; //TODO: replace with a `-K` arg key entry +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 +time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC //Scrambler uint8_t scr_bytes[16]; @@ -49,7 +49,7 @@ void scrambler_sequence_generator () 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 + //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) { @@ -60,10 +60,10 @@ void scrambler_sequence_generator () } //TODO: Set Frame Type based on scrambler_subtype value - if (debug_mode == 1) + if (debug_mode > 1) { - fprintf (stderr, "\nScrambler Key: %X; Seed: %X; Subtype: %d;", scrambler_key, lfsr, scrambler_subtype); - fprintf (stderr, "\n pN: "); //debug + fprintf (stderr, "\nScrambler Key: 0x%06X; Seed: 0x%06X; Subtype: %02d;", scrambler_key, lfsr, scrambler_subtype); + fprintf (stderr, "\n pN: "); } //run pN sequence with taps specified @@ -97,7 +97,7 @@ void scrambler_sequence_generator () if (scrambler_subtype == 2) scrambler_seed &= 0xFFFFFF; else scrambler_seed &= 0xFF; - if (debug_mode == 1) + if (debug_mode > 1) { //debug packed bytes for (i = 0; i < 16; i++) @@ -107,6 +107,59 @@ void scrambler_sequence_generator () } +void usage() +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "-K - AES Encryption (-K 7777777777777777777777777777777777777777777777777777777777777777),\n"); + fprintf(stderr, "-k - Scrambler Encryption -k 123456,\n"); + fprintf(stderr, "-D - Debug Mode,\n"); + fprintf(stderr, "-h - help / print usage,\n"); +} + +//convert a user string (as hex octets) into a uint8_t array for key +void parse_raw_key_string (char * input) +{ + uint8_t * raw = key; //set pointer to the key array + + //since we want this as octets, get strlen value, then divide by two + uint16_t len = strlen((const char*)input); + + //if zero is returned, just do two + if (len == 0) len = 2; + + //if odd number, then user didn't pass complete octets, but just add one to len value to make it even + if (len&1) len++; + + //divide by two to get octet len + len /= 2; + + //sanity check, maximum len should not exceed 32 for an AES key + if (len > 32) len = 32; + + char octet_char[3]; + octet_char[2] = 0; + uint16_t k = 0; + uint16_t i = 0; + + //debug + // fprintf (stderr, "\nRaw Len: %d; Raw Octets:", len); + + for (i = 0; i < len; i++) + { + strncpy (octet_char, input+k, 2); + octet_char[2] = 0; + sscanf (octet_char, "%hhX", &raw[i]); + + //debug + // fprintf (stderr, " (%s)", octet_char); + // fprintf (stderr, " %02X", raw[i]); + + k += 2; + } + + // fprintf (stderr, "\n"); +} + //main routine int main(int argc, char* argv[]) { @@ -115,56 +168,68 @@ int main(int argc, char* argv[]) //printf("%d -> %d -> %d\n", 1, intrl_seq[1], intrl_seq[intrl_seq[1]]); //interleaver bijective reciprocality test, f(f(x))=x //return 0; - //test only, delete next two lines later - debug_mode = 1; - encryption = 2; - - srand(time(NULL)); //seed random number generator + srand(time(NULL)); //random number generator (for IV rand() seed value) memset(key, 0, 32*sizeof(uint8_t)); memset(iv, 0, 16*sizeof(uint8_t)); - //TODO: Redo args so we can get more than one at the same time - //copy and paste from m17-packet-encode - - //debug mode - if(argc>1 && strstr(argv[1], "-D")) + //scan command line options for input data (purely optional) + if(argc>=1) { - debug_mode = 1; - } - - //encryption init - if(argc>1 && strstr(argv[1], "-K")) - { - //hard coded key - for (uint8_t i = 0; i < 32; i++) - key[i] = 0x77; - - if (debug_mode == 1) + for(uint8_t i=1; i1 && strstr(argv[1], "-k")) - { - // scrambler_key = atoi(argv[2]); //would prefer to get the hex input, but good enough to test with - scrambler_key = 0x123456; - scrambler_seed = scrambler_key; //initialize the seed with the key value - encryption=1; //Scrambler key was passed } if(encryption==2) { - //TODO: read key for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); for(uint8_t i=3; i<14; i++) @@ -176,13 +241,13 @@ int main(int argc, char* argv[]) //broadcast memset(next_lsf.dst, 0xFF, 6*sizeof(uint8_t)); - //AB1CDE + //N0CALL next_lsf.src[0] = 0x00; next_lsf.src[1] = 0x00; - next_lsf.src[2] = 0x1F; - next_lsf.src[3] = 0x24; - next_lsf.src[4] = 0x5D; - next_lsf.src[5] = 0x51; + next_lsf.src[2] = 0x4B; + next_lsf.src[3] = 0x13; + next_lsf.src[4] = 0xD1; + next_lsf.src[5] = 0x06; if (encryption == 2) //AES ENC, 3200 voice { @@ -383,9 +448,9 @@ int main(int argc, char* argv[]) //DEBUG: //AES -//encode debug with -- ./m17-coder-sym -K > float.sym +//encode debug with -- ./m17-coder-sym -D -K 7777777777777777777777777777777777777777777777777777777777777777 > float.sym //decode debug with -- m17-fme -r -f float.sym -v 1 -E '7777777777777777 7777777777777777 7777777777777777 7777777777777777' //Scrambler -//encode debug with -- ./m17-coder-sym -k > scr.sym +//encode debug with -- ./m17-coder-sym -D -k 123456 > scr.sym //decode debug with -- m17-fme -r -f scr.sym -v 1 -e 123456 From a0673a808216eb3a2fb15e53257647208c430e7d Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 19 Jun 2024 10:19:09 -0400 Subject: [PATCH 21/33] Delete m17-coder-sym-debug (integrated into m17-coder-sym); .gitignore .txt files, remove m17-coder-sym-debug; --- .gitignore | 4 +- SP5WWP/m17-coder/Makefile | 8 +- SP5WWP/m17-coder/m17-coder-sym-debug.c | 377 ------------------------- 3 files changed, 5 insertions(+), 384 deletions(-) delete mode 100644 SP5WWP/m17-coder/m17-coder-sym-debug.c diff --git a/.gitignore b/.gitignore index 82dd2c9..c593a2d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ /SP5WWP/grc/*.py /SP5WWP/m17-coder/m17-coder-sym -/SP5WWP/m17-coder/m17-coder-sym-debug /SP5WWP/m17-decoder/m17-decoder-sym /SP5WWP/m17-packet/m17-packet-encode /SP5WWP/m17-packet/m17-packet-decode @@ -10,4 +9,5 @@ *.wav *.bin *.sym -*.patch \ No newline at end of file +*.patch +*.txt \ No newline at end of file diff --git a/SP5WWP/m17-coder/Makefile b/SP5WWP/m17-coder/Makefile index 779527f..c302174 100644 --- a/SP5WWP/m17-coder/Makefile +++ b/SP5WWP/m17-coder/Makefile @@ -1,10 +1,8 @@ -all: m17-coder-sym m17-coder-sym-debug - m17-coder-sym: m17-coder-sym.c gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym.c -o m17-coder-sym -lm -lm17 -m17-coder-sym-debug: m17-coder-sym-debug.c - gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym-debug.c -o m17-coder-sym-debug -lm -lm17 +install: + sudo cp m17-coder-sym /usr/local/bin clean: - rm -f m17-coder-sym m17-coder-sym-debug + rm -f m17-coder-sym diff --git a/SP5WWP/m17-coder/m17-coder-sym-debug.c b/SP5WWP/m17-coder/m17-coder-sym-debug.c deleted file mode 100644 index 1d8cb86..0000000 --- a/SP5WWP/m17-coder/m17-coder-sym-debug.c +++ /dev/null @@ -1,377 +0,0 @@ -#include -#include -#include -#include -#include - -//libm17 -#include -//tinier-aes -#include "../../tinier-aes/aes.c" - -//#define FN60_DEBUG - -struct LSF lsf, next_lsf; - -uint8_t lich[6]; //48 bits packed raw, unencoded LICH -uint8_t lich_encoded[12]; //96 bits packed, encoded LICH -uint8_t enc_bits[SYM_PER_PLD*2]; //type-2 bits, unpacked -uint8_t rf_bits[SYM_PER_PLD*2]; //type-4 bits, unpacked - -float frame_buff[192]; -uint32_t frame_buff_cnt; - -uint8_t data[16], next_data[16]; //raw payload, packed bits -uint16_t fn=0; //16-bit Frame Number (for the stream mode) -uint8_t lich_cnt=0; //0..5 LICH counter -uint8_t got_lsf=0; //have we filled the LSF struct yet? -uint8_t finished=0; - -//encryption -uint8_t encryption=0; -int aes_type = 1; //1=AES128, 2=AES192, 3=AES256 - -//AES -uint8_t key[32]; //TODO: replace with a `-K` arg key entry -uint8_t iv[16]; - -time_t epoch = 1577836800L; //Jan 1, 2020, 00:00:00 UTC - -//Scrambler -uint8_t scr_bytes[96]; -uint8_t scrambler_pn[768]; -uint32_t scrambler_key=0; -uint32_t byte_counter=0; - -//scrambler pn sequence generation -void pn_sequence_generator () -{ - int i = 0; - uint32_t lfsr, bit; - uint8_t subtype = 0; - lfsr = scrambler_key; - - if (lfsr > 0 && lfsr <= 0xFF) subtype = 0; // 8-bit key - else if (lfsr > 0xFF && lfsr <= 0xFFFF) subtype = 1; //16-bit key - else if (lfsr > 0xFFFF && lfsr <= 0xFFFFFF) subtype = 2; //24-bit key - else subtype = 0; // 8-bit key (default) - - //TODO: Set Frame Type based on subtype value - - fprintf (stderr, "\nScrambler Key: %X; Subtype: %d;", lfsr, subtype); - fprintf (stderr, "\n pN: "); //debug - - //run pN sequence with taps specified - for (i = 0; i < 128*6; i++) - { - //get feedback bit with specidifed taps, depending on the subtype - if (subtype == 0) - bit = (lfsr >> 7) ^ (lfsr >> 5) ^ (lfsr >> 4) ^ (lfsr >> 3); - else if (subtype == 1) - bit = (lfsr >> 15) ^ (lfsr >> 14) ^ (lfsr >> 12) ^ (lfsr >> 3); - else if (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; //trancate lfsr to 24-bit (really doesn't matter) - scrambler_pn[i] = lfsr & 1; - - //debug - // if ((i != 0) && (i%64 == 0) ) fprintf (stderr, " \n "); - // fprintf (stderr, "%d", scrambler_pn[i]); - - } - - //pack bit array into byte array for easy data XOR - pack_bit_array_into_byte_array(scrambler_pn, scr_bytes, 96); - - //debug packed bytes - for (i = 0; i < 96; i++) - { - if ((i != 0) && (i%16 == 0) ) fprintf (stderr, " \n "); - fprintf (stderr, " %02X", scr_bytes[i]); - } - - fprintf (stderr, "\n"); -} - -//main routine -int main(int argc, char* argv[]) -{ - //debug - //printf("%06X\n", golay24_encode(1)); //golay encoder codeword test - //printf("%d -> %d -> %d\n", 1, intrl_seq[1], intrl_seq[intrl_seq[1]]); //interleaver bijective reciprocality test, f(f(x))=x - //return 0; - - srand(time(NULL)); //seed random number generator - memset(key, 0, 32*sizeof(uint8_t)); - memset(iv, 0, 16*sizeof(uint8_t)); - - //encryption init - if(argc>1 && strstr(argv[1], "-K")) - encryption=2; //AES key was passed - - if(argc>1 && strstr(argv[1], "-k")) - { - // scrambler_key = atoi(argv[2]); //would prefer to get the hex input, but good enough to test with - scrambler_key = 0x123456; - encryption=1; //Scrambler key was passed - } - - if(encryption==2) - { - //TODO: read user input key - - //generate random key - // for (uint8_t i = 0; i < 32; i++) - // key[i] = rand() & 0xFF; - - //hard coded key - for (uint8_t i = 0; i < 32; i++) - key[i] = 0x77; - - //print the random key - fprintf (stderr, "\nAES Key:"); - for (uint8_t i = 0; i < 32; i++) - { - if (i == 16) - fprintf (stderr, "\n "); - fprintf (stderr, " %02X", key[i]); - } - fprintf (stderr, "\n"); - - // *((int32_t*)&iv[0])=(uint32_t)time(NULL)-(uint32_t)epoch; //timestamp //note: I don't think this works as intended - for(uint8_t i=0; i<4; i++) iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); - for(uint8_t i=3; i<14; i++) iv[i] = rand() & 0xFF; //10 random bytes - } - - memset(next_lsf.dst, 0xFF, 6*sizeof(uint8_t)); //broadcast - - //AB1CDE - next_lsf.src[0] = 0x00; - next_lsf.src[1] = 0x00; - next_lsf.src[2] = 0x1F; - next_lsf.src[3] = 0x24; - next_lsf.src[4] = 0x5D; - next_lsf.src[5] = 0x51; - - if (encryption == 2) //AES ENC, 3200 voice - { - next_lsf.type[0] = 0x03; - next_lsf.type[1] = 0x95; - } - else if (encryption == 1) - { - pn_sequence_generator(); - next_lsf.type[0] = 0x03; - next_lsf.type[1] = 0xCD; - } - else //no enc or enc_st field, normal 3200 voice - { - next_lsf.type[0] = 0x00; - next_lsf.type[1] = 0x05; - } - - finished = 0; - - if (encryption == 2) - { - memcpy(&(next_lsf.meta), iv, 14); //AES encryption enabled - use 112 bits of IV - } - else //scrambler, or clear - { - memset(next_lsf.meta, 0, 14*sizeof(uint8_t)); - } - - // while(!finished) - for (uint8_t z = 0; z < 31; z++) //just crank out 5 superframes - { - if(lich_cnt == 0) - { - lsf = next_lsf; - - //calculate LSF CRC - uint16_t ccrc=LSF_CRC(&lsf); - lsf.crc[0]=ccrc>>8; - lsf.crc[1]=ccrc&0xFF; - } - - memset(next_data, 0, sizeof(next_data)); - memcpy(data, next_data, sizeof(data)); - - if (encryption==2) //AES encryption enabled - use 112 bits of IV - { - memcpy(&(next_lsf.meta), iv, 14); - iv[14] = (fn >> 8) & 0x7F; - iv[15] = (fn >> 0) & 0xFF; - } - else //Scrambler, or Clear - { - memset(next_lsf.meta, 0, 14*sizeof(uint8_t)); - } - - if(got_lsf) //stream frames - { - //send stream frame syncword - frame_buff_cnt=0; - send_syncword(frame_buff, &frame_buff_cnt, SYNC_STR); - - //extract LICH from the whole LSF - extract_LICH(lich, lich_cnt, &lsf); - - //encode the LICH - encode_LICH(lich_encoded, lich); - - //unpack LICH (12 bytes) - unpack_LICH(enc_bits, lich_encoded); - - //encrypt - if(encryption==2) - { - fprintf(stderr, "FN: %04X; IV: ", fn); - for(uint8_t i=0; i<16; i++) - fprintf(stderr, "%02X", iv[i]); - fprintf(stderr, "\n"); - - fprintf(stderr, "\t IN: "); - for(uint8_t i=0; i<16; i++) - fprintf(stderr, "%02X", data[i]); - fprintf(stderr, "\n"); - - aes_ctr_bytewise_payload_crypt(iv, key, data, aes_type); - - fprintf(stderr, "\t OUT: "); - for(uint8_t i=0; i<16; i++) - fprintf(stderr, "%02X", data[i]); - fprintf(stderr, "\n"); - } - else if (encryption == 1) - { - fprintf(stderr, "FN: %04X; ", fn); - fprintf(stderr, "IN: "); - for(uint8_t i=0; i<16; i++) - fprintf(stderr, "%02X", data[i]); - fprintf(stderr, "\n"); - - for(uint8_t i=0; i<16; i++) - { - data[i] ^= scr_bytes[byte_counter%96]; - byte_counter++; - } - - fprintf(stderr, " "); - fprintf(stderr, "OUT: "); - for(uint8_t i=0; i<16; i++) - fprintf(stderr, "%02X", data[i]); - fprintf(stderr, "\n"); - } - - //encode the rest of the frame (starting at bit 96 - 0..95 are filled with LICH) - conv_encode_stream_frame(&enc_bits[96], data, finished ? (fn | 0x8000) : fn); - - //reorder bits - reorder_bits(rf_bits, enc_bits); - - //randomize - randomize_bits(rf_bits); - - //send dummy symbols (debug) - /*float s=0.0; - for(uint8_t i=0; i float.sym -//decode debug with -- m17-fme -r -f float.sym -v 1 -E '7777777777777777 7777777777777777 7777777777777777 7777777777777777' - -//Scrambler -//encode debug with -- ./m17-coder-sym-debug -k > scr.sym -//decode debug with -- m17-fme -r -f scr.sym -v 1 -e 123456 \ No newline at end of file From e54d68a6e50fe510d79590f7108583c7fa175db2 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 19 Jun 2024 12:07:31 -0400 Subject: [PATCH 22/33] Update to use tinier-aes .h file found on that dev branch; --- SP5WWP/m17-coder/Makefile | 2 +- SP5WWP/m17-coder/m17-coder-sym.c | 2 +- tinier-aes | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SP5WWP/m17-coder/Makefile b/SP5WWP/m17-coder/Makefile index c302174..f392d02 100644 --- a/SP5WWP/m17-coder/Makefile +++ b/SP5WWP/m17-coder/Makefile @@ -1,5 +1,5 @@ m17-coder-sym: m17-coder-sym.c - gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym.c -o m17-coder-sym -lm -lm17 + gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym.c ../../tinier-aes/aes.c -o m17-coder-sym -lm -lm17 install: sudo cp m17-coder-sym /usr/local/bin diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index e940c20..9685e50 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -7,7 +7,7 @@ //libm17 #include //tinier-aes -#include "../../tinier-aes/aes.c" +#include "../../tinier-aes/aes.h" struct LSF lsf, next_lsf; diff --git a/tinier-aes b/tinier-aes index a15f518..f602803 160000 --- a/tinier-aes +++ b/tinier-aes @@ -1 +1 @@ -Subproject commit a15f5186a7b344ef8a783ba3118e7407d3cd22c8 +Subproject commit f602803fde808f8b22a1c724857a3928c91169d3 From 2c2ca75a2afa53e2fe5a02e8e2490bd9024e9be1 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 19 Jun 2024 12:44:50 -0400 Subject: [PATCH 23/33] Load AES Key from keyfile with -F option; --- SP5WWP/m17-coder/aeskey.txt | 1 + SP5WWP/m17-coder/m17-coder-sym.c | 49 ++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 SP5WWP/m17-coder/aeskey.txt diff --git a/SP5WWP/m17-coder/aeskey.txt b/SP5WWP/m17-coder/aeskey.txt new file mode 100644 index 0000000..b010a83 --- /dev/null +++ b/SP5WWP/m17-coder/aeskey.txt @@ -0,0 +1 @@ +1234567890ABCDEF7777777777777777FEDCBA09876543218888888888888888 \ No newline at end of file diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 9685e50..ab6a2bb 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -110,8 +110,9 @@ void scrambler_sequence_generator () void usage() { fprintf(stderr, "Usage:\n"); - fprintf(stderr, "-K - AES Encryption (-K 7777777777777777777777777777777777777777777777777777777777777777),\n"); - fprintf(stderr, "-k - Scrambler Encryption -k 123456,\n"); + fprintf(stderr, "-K - AES Encryption Hex String (-K 7777777777777777777777777777777777777777777777777777777777777777),\n"); + fprintf(stderr, "-F - AES Encryption From File (-F aeskey.txt),\n"); + fprintf(stderr, "-k - Scrambler Encryption Hex String (-k 123456),\n"); fprintf(stderr, "-D - Debug Mode,\n"); fprintf(stderr, "-h - help / print usage,\n"); } @@ -194,6 +195,46 @@ int main(int argc, char* argv[]) fprintf (stderr, "\n"); + encryption=2; //AES key was passed + } + if(argv[i][1]=='F') //-F - AES Encryption (key from 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; + + fp = fopen(fname, "r"); + if (!fp) + { + fprintf(stderr, "Failed to load file %s.\n", fname); + return -1; + } + source_str = (char*)malloc(64); + fread(source_str, 1, 64, fp); + fclose(fp); + + parse_raw_key_string (source_str); + + free(source_str); + + fprintf (stderr, "AES Key:"); + for (uint8_t i = 0; i < 32; i++) + { + if (i == 16) + fprintf (stderr, "\n "); + fprintf (stderr, " %02X", key[i]); + } + fprintf (stderr, "\n"); + + encryption=2; //AES key was passed } else if(argv[i][1]=='k') //-k - Scrambler Encryption @@ -454,3 +495,7 @@ int main(int argc, char* argv[]) //Scrambler //encode debug with -- ./m17-coder-sym -D -k 123456 > scr.sym //decode debug with -- m17-fme -r -f scr.sym -v 1 -e 123456 + +//AES (with file import) +//encode debug with -- ./m17-coder-sym -D -F aeskey.txt > float.sym +//decode debug with -- m17-fme -r -f float.sym -v 1 -E '7777777777777777 7777777777777777 7777777777777777 7777777777777777' From f876f9ce40dddd0173066313fe8746a3ddc790d6 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 19 Jun 2024 12:49:08 -0400 Subject: [PATCH 24/33] Fix Boo Boo; --- SP5WWP/m17-coder/m17-coder-sym.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index ab6a2bb..1097ba8 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -197,7 +197,7 @@ int main(int argc, char* argv[]) encryption=2; //AES key was passed } - if(argv[i][1]=='F') //-F - AES Encryption (key from file) + else if(argv[i][1]=='F') //-F - AES Encryption (key from file) { char fname[128]={'\0'}; //output file if(strlen(&argv[i+1][0])>0) From a40d284e966c3bda99ef5149f49fc95a1266278b Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 19 Jun 2024 12:54:12 -0400 Subject: [PATCH 25/33] Fix Debug Test Line; --- SP5WWP/m17-coder/m17-coder-sym.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 1097ba8..6e15d7e 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -498,4 +498,4 @@ int main(int argc, char* argv[]) //AES (with file import) //encode debug with -- ./m17-coder-sym -D -F aeskey.txt > float.sym -//decode debug with -- m17-fme -r -f float.sym -v 1 -E '7777777777777777 7777777777777777 7777777777777777 7777777777777777' +//decode debug with -- m17-fme -r -f float.sym -v 1 -E '1234567890ABCDEF 7777777777777777 FEDCBA0987654321 8888888888888888' From 073857e22c31dfb4ed50dcbc8003ec358c5e144d Mon Sep 17 00:00:00 2001 From: Wojciech Kaczmarski Date: Thu, 20 Jun 2024 13:51:26 +0200 Subject: [PATCH 26/33] slight code cleanups -fixed key parsing from hex string --- SP5WWP/m17-coder/Makefile | 2 +- SP5WWP/m17-coder/m17-coder-sym.c | 234 ++++++++++++++++++------------- 2 files changed, 140 insertions(+), 96 deletions(-) diff --git a/SP5WWP/m17-coder/Makefile b/SP5WWP/m17-coder/Makefile index f392d02..f6fa593 100644 --- a/SP5WWP/m17-coder/Makefile +++ b/SP5WWP/m17-coder/Makefile @@ -1,5 +1,5 @@ m17-coder-sym: m17-coder-sym.c - gcc -I ../../libm17 -L ../../libm17 -O2 -Wall -Wextra m17-coder-sym.c ../../tinier-aes/aes.c -o m17-coder-sym -lm -lm17 + gcc -O2 -Wall -Wextra m17-coder-sym.c ../../tinier-aes/aes.c -o m17-coder-sym -lm -lm17 install: sudo cp m17-coder-sym /usr/local/bin diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 6e15d7e..44c07e0 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -5,7 +5,7 @@ #include //libm17 -#include +#include "../../libm17/m17.h" //tinier-aes #include "../../tinier-aes/aes.h" @@ -35,7 +35,6 @@ 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_key=0; uint32_t scrambler_seed=0; int8_t scrambler_subtype = -1; @@ -43,7 +42,7 @@ int8_t scrambler_subtype = -1; uint8_t debug_mode=0; //scrambler pn sequence generation -void scrambler_sequence_generator () +void scrambler_sequence_generator() { int i = 0; uint32_t lfsr, bit; @@ -62,7 +61,7 @@ void scrambler_sequence_generator () //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_key, lfsr, scrambler_subtype); + fprintf (stderr, "\nScrambler Key: 0x%06X; Seed: 0x%06X; Subtype: %02d;", scrambler_seed, lfsr, scrambler_subtype); fprintf (stderr, "\n pN: "); } @@ -110,55 +109,66 @@ void scrambler_sequence_generator () void usage() { fprintf(stderr, "Usage:\n"); - fprintf(stderr, "-K - AES Encryption Hex String (-K 7777777777777777777777777777777777777777777777777777777777777777),\n"); - fprintf(stderr, "-F - AES Encryption From File (-F aeskey.txt),\n"); - fprintf(stderr, "-k - Scrambler Encryption Hex String (-k 123456),\n"); - fprintf(stderr, "-D - Debug Mode,\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, "-D - Debug mode,\n"); fprintf(stderr, "-h - help / print usage,\n"); } //convert a user string (as hex octets) into a uint8_t array for key -void parse_raw_key_string (char * input) +void parse_raw_key_string(uint8_t* dest, const char* inp) { - uint8_t * raw = key; //set pointer to the key array + uint16_t len = strlen(inp); - //since we want this as octets, get strlen value, then divide by two - uint16_t len = strlen((const char*)input); + if(len==0) return; //return silently and pretend nothing happened - //if zero is returned, just do two - if (len == 0) len = 2; + memset(dest, 0, len/2); //one character represents half of a byte - //if odd number, then user didn't pass complete octets, but just add one to len value to make it even - if (len&1) len++; - - //divide by two to get octet len - len /= 2; - - //sanity check, maximum len should not exceed 32 for an AES key - if (len > 32) len = 32; - - char octet_char[3]; - octet_char[2] = 0; - uint16_t k = 0; - uint16_t i = 0; - - //debug - // fprintf (stderr, "\nRaw Len: %d; Raw Octets:", len); - - for (i = 0; i < len; i++) + if(!(len%2)) //length even? { - strncpy (octet_char, input+k, 2); - octet_char[2] = 0; - sscanf (octet_char, "%hhX", &raw[i]); - - //debug - // fprintf (stderr, " (%s)", octet_char); - // fprintf (stderr, " %02X", raw[i]); - - k += 2; + for(uint8_t i=0; i='a') + dest[i/2]|=(inp[i]-'a')*0x10; + else if(inp[i]>='A') + dest[i/2]|=(inp[i]-'A')*0x10; + else if(inp[i]>='0') + dest[i/2]|=(inp[i]-'0')*0x10; + + if(inp[i+1]>='a') + dest[i/2]|=inp[i+1]-'a'; + else if(inp[i+1]>='A') + dest[i/2]|=inp[i+1]-'A'; + else if(inp[i+1]>='0') + dest[i/2]|=inp[i+1]-'0'; + } } + else + { + if(inp[0]>='a') + dest[0]|=inp[0]-'a'; + else if(inp[0]>='A') + dest[0]|=inp[0]-'A'; + else if(inp[0]>='0') + dest[0]|=inp[0]-'0'; - // fprintf (stderr, "\n"); + for(uint8_t i=1; i='a') + dest[i/2+1]|=(inp[i]-'a')*0x10; + else if(inp[i]>='A') + dest[i/2+1]|=(inp[i]-'A')*0x10; + else if(inp[i]>='0') + dest[i/2+1]|=(inp[i]-'0')*0x10; + + if(inp[i+1]>='a') + dest[i/2+1]|=inp[i+1]-'a'; + else if(inp[i+1]>='A') + dest[i/2+1]|=inp[i+1]-'A'; + else if(inp[i+1]>='0') + dest[i/2+1]|=inp[i+1]-'0'; + } + } } //main routine @@ -182,73 +192,107 @@ int main(int argc, char* argv[]) { if(argv[i][1]=='K') //-K - AES Encryption { - - parse_raw_key_string (argv[i+1]); - - fprintf (stderr, "AES Key:"); - for (uint8_t i = 0; i < 32; i++) + if(strstr(argv[i+1], ".")) //if the next arg contains a dot - read key from a text file { - if (i == 16) - fprintf (stderr, "\n "); - fprintf (stderr, " %02X", key[i]); + 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; i0) - memcpy(fname, &argv[i+1][0], strlen(argv[i+1])); else { - fprintf(stderr, "Invalid filename. Exiting...\n"); - return -1; + //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; i24/4) //24-bit is the largest seed value + { + fprintf(stderr, "Invalid key length.\n"); + return -1; + } - fprintf (stderr, "Scrambler Key: 0x%06X;", scrambler_key); + parse_raw_key_string(key, argv[i+1]); + scrambler_seed = (key[0] << 16) | (key[1] << 8) | (key[2] << 0); - scrambler_seed = scrambler_key; //initialize the seed with the key value + if(length<=2) + fprintf(stderr, "Scrambler key: 0x%02X (8-bit)\n", scrambler_seed>>16); + else if(length<=4) + fprintf(stderr, "Scrambler key: 0x%04X (16-bit)\n", scrambler_seed>>8); + else + fprintf(stderr, "Scrambler key: 0x%06X (24-bit)\n", scrambler_seed); + //fprintf(stderr, "Scrambler key: %06X\n", scrambler_seed); encryption=1; //Scrambler key was passed - } else if(argv[i][1]=='D') //-D - Debug Mode { From 5d3341bd724a619041a10be6bf6e804bf9b1b13f Mon Sep 17 00:00:00 2001 From: Wojciech Kaczmarski <44336093+sp5wwp@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:12:47 +0200 Subject: [PATCH 27/33] Update m17-coder-sym.c Fixed hex parser bug --- SP5WWP/m17-coder/m17-coder-sym.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 44c07e0..5069d7e 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -129,16 +129,16 @@ void parse_raw_key_string(uint8_t* dest, const char* inp) for(uint8_t i=0; i='a') - dest[i/2]|=(inp[i]-'a')*0x10; + dest[i/2]|=(inp[i]-'a'+10)*0x10; else if(inp[i]>='A') - dest[i/2]|=(inp[i]-'A')*0x10; + dest[i/2]|=(inp[i]-'A'+10)*0x10; else if(inp[i]>='0') dest[i/2]|=(inp[i]-'0')*0x10; if(inp[i+1]>='a') - dest[i/2]|=inp[i+1]-'a'; + dest[i/2]|=inp[i+1]-'a'+10; else if(inp[i+1]>='A') - dest[i/2]|=inp[i+1]-'A'; + dest[i/2]|=inp[i+1]-'A'+10; else if(inp[i+1]>='0') dest[i/2]|=inp[i+1]-'0'; } @@ -146,25 +146,25 @@ void parse_raw_key_string(uint8_t* dest, const char* inp) else { if(inp[0]>='a') - dest[0]|=inp[0]-'a'; + dest[0]|=inp[0]-'a'+10; else if(inp[0]>='A') - dest[0]|=inp[0]-'A'; + dest[0]|=inp[0]-'A'+10; else if(inp[0]>='0') dest[0]|=inp[0]-'0'; for(uint8_t i=1; i='a') - dest[i/2+1]|=(inp[i]-'a')*0x10; + dest[i/2+1]|=(inp[i]-'a'+10)*0x10; else if(inp[i]>='A') - dest[i/2+1]|=(inp[i]-'A')*0x10; + dest[i/2+1]|=(inp[i]-'A'+10)*0x10; else if(inp[i]>='0') dest[i/2+1]|=(inp[i]-'0')*0x10; if(inp[i+1]>='a') - dest[i/2+1]|=inp[i+1]-'a'; + dest[i/2+1]|=inp[i+1]-'a'+10; else if(inp[i+1]>='A') - dest[i/2+1]|=inp[i+1]-'A'; + dest[i/2+1]|=inp[i+1]-'A'+10; else if(inp[i+1]>='0') dest[i/2+1]|=inp[i+1]-'0'; } From 1222ad4c313d5063f82ab297bb371e587516f9c9 Mon Sep 17 00:00:00 2001 From: Wojciech Kaczmarski <44336093+sp5wwp@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:14:39 +0200 Subject: [PATCH 28/33] move gr flowgraph from the `auth` branch --- SP5WWP/grc/m17_streamer.grc | 62 +++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/SP5WWP/grc/m17_streamer.grc b/SP5WWP/grc/m17_streamer.grc index 2392333..611fd33 100644 --- a/SP5WWP/grc/m17_streamer.grc +++ b/SP5WWP/grc/m17_streamer.grc @@ -28,11 +28,35 @@ options: bus_sink: false bus_source: false bus_structure: null - coordinate: [520, 12.0] + coordinate: [8, 4.0] rotation: 0 state: enabled blocks: +- name: can + id: variable + parameters: + comment: '' + value: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 4.0] + rotation: 0 + state: true +- name: sign + id: variable + parameters: + comment: '' + value: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [256, 4.0] + rotation: 0 + state: true - name: blocks_file_sink_0 id: blocks_file_sink parameters: @@ -40,15 +64,15 @@ blocks: alias: '' append: 'False' comment: '' - file: ../stream_fifo + file: /tmp/fifo0 type: byte - unbuffered: 'False' + unbuffered: 'True' vlen: '1' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [696, 172.0] + coordinate: [696, 292.0] rotation: 0 state: true - name: blocks_stream_mux_0 @@ -67,7 +91,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [360, 128.0] + coordinate: [360, 248.0] rotation: 0 state: enabled - name: blocks_throttle2_0 @@ -78,8 +102,8 @@ blocks: comment: '' ignoretag: 'True' limit: auto - maximum: '0.1' - maxoutbuf: '0' + maximum: 6+6+2+14+16 + maxoutbuf: 6+6+2+14+16 minoutbuf: '0' samples_per_second: (6+6+2+14+16)*(1000/40) type: byte @@ -88,7 +112,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [536, 180.0] + coordinate: [536, 300.0] rotation: 0 state: true - name: blocks_vector_source_x_0 @@ -108,7 +132,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [112, 12.0] + coordinate: [112, 132.0] rotation: 0 state: true - name: blocks_vector_source_x_0_0 @@ -128,7 +152,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [112, 92.0] + coordinate: [112, 212.0] rotation: 0 state: true - name: blocks_vector_source_x_0_1 @@ -142,13 +166,13 @@ blocks: repeat: 'True' tags: '[]' type: byte - vector: (0x00, 0x05) + vector: ((sign<<3)|(can>>1), ((can&1)<<7)|0x05) vlen: '1' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [112, 172.0] + coordinate: [112, 292.0] rotation: 0 state: true - name: blocks_vector_source_x_0_2 @@ -169,7 +193,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [112, 332.0] + coordinate: [112, 452.0] rotation: 0 state: true - name: blocks_vector_source_x_0_2_0 @@ -190,7 +214,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [112, 252.0] + coordinate: [112, 372.0] rotation: 0 state: true - name: note_0 @@ -203,7 +227,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [16, 28.0] + coordinate: [16, 148.0] rotation: 0 state: true - name: note_0_0 @@ -216,7 +240,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [16, 108.0] + coordinate: [16, 228.0] rotation: 0 state: true - name: note_0_1 @@ -229,7 +253,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [16, 188.0] + coordinate: [16, 308.0] rotation: 0 state: true - name: note_0_2 @@ -242,7 +266,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [16, 348.0] + coordinate: [16, 468.0] rotation: 0 state: true - name: note_0_2_0 @@ -255,7 +279,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [16, 268.0] + coordinate: [16, 388.0] rotation: 0 state: true From 2d80ef107b78db687bd5cdb7d71d4b6d76085412 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sat, 22 Jun 2024 14:03:13 -0400 Subject: [PATCH 29/33] Merge WIP: m17-coder-sym working with sig and crypto code, and seems to work as-is with encrypted payload and non encrypted sig; TODO: Thorough Testing and Code Cleanup; --- SP5WWP/m17-coder/m17-coder-sym.c | 407 +++++++++++++++++- .../{aeskey.txt => sample_aes_key.txt} | 0 2 files changed, 394 insertions(+), 13 deletions(-) rename SP5WWP/m17-coder/{aeskey.txt => sample_aes_key.txt} (100%) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index e5bf3b2..89cde43 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -2,11 +2,14 @@ #include #include #include +#include //libm17 #include "../../libm17/m17.h" //micro-ecc #include "../../micro-ecc/uECC.h" +//tinier-aes +#include "../../tinier-aes/aes.h" //#define FN60_DEBUG @@ -29,15 +32,100 @@ uint8_t finished=0; //no more data at stdin? //used for signatures uint8_t digest[16]={0}; //16-byte field for the stream digest uint8_t signed_str=0; //is the stream supposed to be signed? +uint8_t priv_key_loaded=0; //do we have a sig key loaded? uint8_t priv_key[32]={0}; //private key uint8_t sig[64]={0}; //ECDSA signature int dummy=0; //dummy var to make compiler quieter +//encryption +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 (preset lsf, type, zero payload for enc testing, etc) +uint8_t debug_mode=0; + +//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"); fprintf(stderr, "-s - Private key for ECDSA signature, 32 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, "-D - Debug mode,\n"); fprintf(stderr, "-h - help / print usage\n"); } @@ -100,6 +188,10 @@ void parse_raw_key_string(uint8_t* dest, const char* inp) //main routine int main(int argc, char* argv[]) { + srand(time(NULL)); //random number generator (for IV rand() seed value) + memset(key, 0, 32*sizeof(uint8_t)); + memset(iv, 0, 16*sizeof(uint8_t)); + //scan command line options for input data (purely optional) if(argc>=1) { @@ -118,9 +210,123 @@ int main(int argc, char* argv[]) } parse_raw_key_string(priv_key, argv[i+1]); - + priv_key_loaded=1; //mainly for debug mode i++; } + else 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; i24/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 + } + else if(argv[i][1]=='D') //-D - Debug Mode + { + debug_mode=1; + } + else if(argv[i][1]=='h') //-h - help / usage { usage(); @@ -136,6 +342,14 @@ int main(int argc, char* argv[]) } } + if(encryption==2) + { + for(uint8_t i=0; i<4; i++) + iv[i] = ((uint32_t)(time(NULL)&0xFFFFFFFF)-(uint32_t)epoch) >> (24-(i*8)); + for(uint8_t i=3; i<14; i++) + iv[i] = rand() & 0xFF; //10 random bytes + } + const struct uECC_Curve_t* curve = uECC_secp256r1(); //send out the preamble @@ -143,12 +357,76 @@ int main(int argc, char* argv[]) send_preamble(frame_buff, &frame_buff_cnt, 0); //0 - LSF preamble, as opposed to 1 - BERT preamble fwrite((uint8_t*)frame_buff, SYM_PER_FRA*sizeof(float), 1, stdout); - //read data - dummy=fread(&(lsf.dst), 6, 1, stdin); - dummy=fread(&(lsf.src), 6, 1, stdin); - dummy=fread(&(lsf.type), 2, 1, stdin); - dummy=fread(&(lsf.meta), 14, 1, stdin); - dummy=fread(data, 16, 1, stdin); + if (debug_mode == 1) + { + //broadcast + memset(lsf.dst, 0xFF, 6*sizeof(uint8_t)); + + //N0CALL + lsf.src[0] = 0x00; + lsf.src[1] = 0x00; + lsf.src[2] = 0x4B; + lsf.src[3] = 0x13; + lsf.src[4] = 0xD1; + lsf.src[5] = 0x06; + + if (encryption == 2) //AES ENC, 3200 voice + { + lsf.type[0] = 0x03; + lsf.type[1] = 0x95; + } + else if (encryption == 1) //Scrambler ENC, 3200 Voice + { + lsf.type[0] = 0x03; + lsf.type[1] = 0xCD; + } + else //no enc or subtype field, normal 3200 voice + { + lsf.type[0] = 0x00; + lsf.type[1] = 0x05; + } + + //a signature key is loaded, OR this bit + if(priv_key_loaded) + { + signed_str = 1; + lsf.type[0] |= 0x8; + } + + //calculate LSF CRC (unclear whether or not this is only + //needed here for debug, or if this is missing on every initial LSF) + uint16_t ccrc=LSF_CRC(&lsf); + lsf.crc[0]=ccrc>>8; + lsf.crc[1]=ccrc&0xFF; + + finished = 0; + + //debug sig with random payloads (don't play the audio) + for (uint8_t i = 0; i < 16; i++) + data[i] = 0x69; //rand() & 0xFF; + } + else + { + //read data + dummy=fread(&(lsf.dst), 6, 1, stdin); + dummy=fread(&(lsf.src), 6, 1, stdin); + dummy=fread(&(lsf.type), 2, 1, stdin); + dummy=fread(&(lsf.meta), 14, 1, stdin); + dummy=fread(data, 16, 1, stdin); + } + + //AES encryption enabled - use 112 bits of IV + if(encryption==2) + { + memcpy(&(lsf.meta), iv, 14); + iv[14] = (fn >> 8) & 0x7F; + iv[15] = (fn >> 0) & 0xFF; + + //re-calculate LSF CRC with IV insertion + uint16_t ccrc=LSF_CRC(&lsf); + lsf.crc[0]=ccrc>>8; + lsf.crc[1]=ccrc&0xFF; + } while(!finished) { @@ -183,12 +461,78 @@ int main(int argc, char* argv[]) got_lsf=1; } - //check if theres any more data - if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; - if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; - if(fread(next_data, 16, 1, stdin)<1) finished=1; + if (debug_mode == 1) + { + //broadcast + memset(next_lsf.dst, 0xFF, 6*sizeof(uint8_t)); + + //N0CALL + next_lsf.src[0] = 0x00; + next_lsf.src[1] = 0x00; + next_lsf.src[2] = 0x4B; + next_lsf.src[3] = 0x13; + next_lsf.src[4] = 0xD1; + next_lsf.src[5] = 0x06; + + if (encryption == 2) //AES ENC, 3200 voice + { + next_lsf.type[0] = 0x03; + next_lsf.type[1] = 0x95; + } + else if (encryption == 1) //Scrambler ENC, 3200 Voice + { + next_lsf.type[0] = 0x03; + next_lsf.type[1] = 0xCD; + } + else //no enc or subtype field, normal 3200 voice + { + next_lsf.type[0] = 0x00; + next_lsf.type[1] = 0x05; + } + + //a signature key is loaded, OR this bit + if(priv_key_loaded) + next_lsf.type[0] |= 0x8; + + finished = 0; + + memset(next_data, 0, sizeof(next_data)); + memcpy(data, next_data, sizeof(data)); + if (fn == 60) + finished = 1; + + //debug sig with random payloads (don't play the audio) + for (uint8_t i = 0; i < 16; i++) + data[i] = 0x69; //rand() & 0xFF; + + } + else + { + //check if theres any more data + if(fread(&(next_lsf.dst), 6, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.src), 6, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.type), 2, 1, stdin)<1) finished=1; + if(fread(&(next_lsf.meta), 14, 1, stdin)<1) finished=1; + if(fread(next_data, 16, 1, stdin)<1) finished=1; + } + + //encrypt + if(encryption==2) + { + memcpy(&(next_lsf.meta), iv, 14); + iv[14] = (fn >> 8) & 0x7F; + iv[15] = (fn >> 0) & 0xFF; + aes_ctr_bytewise_payload_crypt(iv, key, data, aes_type); + } + + else if (encryption == 1) + { + scrambler_sequence_generator(); + for(uint8_t i=0; i<16; i++) + { + data[i] ^= scr_bytes[i]; + } + } if(!finished) { @@ -312,6 +656,19 @@ int main(int argc, char* argv[]) for(uint8_t i=0; i scr.sym +//decode debug with -- m17-fme -r -f scr.sym -v 1 -e 123456 + +//AES (with file import) +//encode debug with -- ./m17-coder-sym -D -K sample_aes_key.txt> float.sym +//decode debug with -- m17-fme -r -f float.sym -v 1 -J sample_aes_key.txt + +//Signatures +//encode debug with -- ./m17-coder-sym -D -s 69b07d7afe7f843e56ecbf536a49461dc5901c975d895bf1649cabff8f9b208b > float.sym +//decode debug with -- cat ../m17-coder/float.sym | ./m17-decoder-sym -s c6c03dd11276aa917e7d83ae16d7f4fbf06f31be5869f9ae8004c329947dc4eeef0d9363653c8edf93e50912c6c515b40e0a8cbeea5e984dbc78e1993c8fbd5d +//decode debug with -- m17-fme -r -f float.sym -v 1 -k ../m17-decoder/sample_pub_key.txt + +//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 -- 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 -- m17-fme -r -f float.sym -v 1 -k ../m17-decoder/sample_pub_key.txt -e 543210 diff --git a/SP5WWP/m17-coder/aeskey.txt b/SP5WWP/m17-coder/sample_aes_key.txt similarity index 100% rename from SP5WWP/m17-coder/aeskey.txt rename to SP5WWP/m17-coder/sample_aes_key.txt From d1e1d9eb8e0081d25c8e2e772a38bce5568f693f Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sat, 22 Jun 2024 15:01:49 -0400 Subject: [PATCH 30/33] Add Crypto Code to m17-decoder-sym.c; --- SP5WWP/m17-coder/m17-coder-sym.c | 9 +- SP5WWP/m17-decoder/Makefile | 2 +- SP5WWP/m17-decoder/m17-decoder-sym.c | 249 +++++++++++++++++++++++++-- 3 files changed, 241 insertions(+), 19 deletions(-) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 89cde43..9460bc9 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -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 diff --git a/SP5WWP/m17-decoder/Makefile b/SP5WWP/m17-decoder/Makefile index fc02191..9b45cb6 100644 --- a/SP5WWP/m17-decoder/Makefile +++ b/SP5WWP/m17-decoder/Makefile @@ -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 diff --git a/SP5WWP/m17-decoder/m17-decoder-sym.c b/SP5WWP/m17-decoder/m17-decoder-sym.c index 933cf44..42d4a0b 100644 --- a/SP5WWP/m17-decoder/m17-decoder-sym.c +++ b/SP5WWP/m17-decoder/m17-decoder-sym.c @@ -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; i24/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= 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 Date: Sat, 22 Jun 2024 15:04:58 -0400 Subject: [PATCH 31/33] Pretty TODO Lists; --- SP5WWP/m17-coder/m17-coder-sym.c | 12 ++++++++++++ SP5WWP/m17-decoder/m17-decoder-sym.c | 3 +++ 2 files changed, 15 insertions(+) diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 9460bc9..42b4124 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -13,6 +13,18 @@ //#define FN60_DEBUG +//TODO: Load Signature Private and Public Keys from file +//TODO: More Thorough Testing to make sure everything is good +//TODO: Round of Cleanup (and test after cleaning up! +//TODO: OR Frametype Bits depending on encryption type, subtype, and signed sig + +//Wishlist: Please Woj, can we use the subtype on AES to signal AES 128, AES 192, or AES 256? +// We already to it for Scrambler + +//Wishlist: way to fix this warning without changing uECC source code or disabling -Wall -Wextra +//../../micro-ecc/curve-specific.inc:544:59: warning: unused parameter ‘curve’ [-Wunused-parameter] +//544 | static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve) { + struct LSF lsf, next_lsf; uint8_t lich[6]; //48 bits packed raw, unencoded LICH diff --git a/SP5WWP/m17-decoder/m17-decoder-sym.c b/SP5WWP/m17-decoder/m17-decoder-sym.c index 42d4a0b..4b1c33e 100644 --- a/SP5WWP/m17-decoder/m17-decoder-sym.c +++ b/SP5WWP/m17-decoder/m17-decoder-sym.c @@ -10,6 +10,9 @@ //tinier-aes #include "../../tinier-aes/aes.h" +//TODO: Load Signature Private and Public Keys from file +//TODO: Fix AES Keyfile loading issue (key is loaded offset by one, arg issue?) + //settings uint8_t decode_callsigns=0; uint8_t show_viterbi_errs=0; From 668924187f687e68481f79c71e092f5c7aced21c Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sat, 22 Jun 2024 20:42:49 -0400 Subject: [PATCH 32/33] Add sample_aes_key.txt to m17-decoder-sym folder; Update Debug Example; --- SP5WWP/m17-coder/m17-coder-sym.c | 2 +- SP5WWP/m17-decoder/sample_aes_key.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 SP5WWP/m17-decoder/sample_aes_key.txt diff --git a/SP5WWP/m17-coder/m17-coder-sym.c b/SP5WWP/m17-coder/m17-coder-sym.c index 42b4124..88cb38c 100644 --- a/SP5WWP/m17-coder/m17-coder-sym.c +++ b/SP5WWP/m17-coder/m17-coder-sym.c @@ -711,7 +711,7 @@ 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 -K 1234567890ABCDEF7777777777777777FEDCBA09876543218888888888888888 +//decode debug with -- cat ../m17-coder/float.sym | ./m17-decoder-sym -s c6c03dd11276aa917e7d83ae16d7f4fbf06f31be5869f9ae8004c329947dc4eeef0d9363653c8edf93e50912c6c515b40e0a8cbeea5e984dbc78e1993c8fbd5d -K sample_aes_key.txt //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 diff --git a/SP5WWP/m17-decoder/sample_aes_key.txt b/SP5WWP/m17-decoder/sample_aes_key.txt new file mode 100644 index 0000000..b010a83 --- /dev/null +++ b/SP5WWP/m17-decoder/sample_aes_key.txt @@ -0,0 +1 @@ +1234567890ABCDEF7777777777777777FEDCBA09876543218888888888888888 \ No newline at end of file From adc523cf5e8185f155d331e450555475eecad18b Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sat, 22 Jun 2024 21:43:31 -0400 Subject: [PATCH 33/33] Add scrambler_seed_calculation function to decoder so seed can be recalculated if missing frame, etc; --- SP5WWP/m17-decoder/m17-decoder-sym.c | 55 ++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/SP5WWP/m17-decoder/m17-decoder-sym.c b/SP5WWP/m17-decoder/m17-decoder-sym.c index 4b1c33e..7660803 100644 --- a/SP5WWP/m17-decoder/m17-decoder-sym.c +++ b/SP5WWP/m17-decoder/m17-decoder-sym.c @@ -11,7 +11,6 @@ #include "../../tinier-aes/aes.h" //TODO: Load Signature Private and Public Keys from file -//TODO: Fix AES Keyfile loading issue (key is loaded offset by one, arg issue?) //settings uint8_t decode_callsigns=0; @@ -57,12 +56,51 @@ 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_key=0; //keep set to initial value for seed calculation function uint32_t scrambler_seed=0; int8_t scrambler_subtype = -1; //debug mode uint8_t debug_mode=0; //TODO: Remove lines looking at this +//this is generating a correct seed value based on the fn value, +//ideally, we would only want to run this under poor signal, frame skips, etc +//Note: Running this every frame will lag if high fn values (observed with test file) +uint32_t scrambler_seed_calculation(int8_t subtype, uint32_t key, int fn) +{ + int i; + uint32_t lfsr, bit; + + lfsr = key; bit = 0; + for (i = 0; i < 128*fn; i++) + { + //get feedback bit with specified taps, depending on the subtype + if (subtype == 0) + bit = (lfsr >> 7) ^ (lfsr >> 5) ^ (lfsr >> 4) ^ (lfsr >> 3); + else if (subtype == 1) + bit = (lfsr >> 15) ^ (lfsr >> 14) ^ (lfsr >> 12) ^ (lfsr >> 3); + else if (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 + lfsr = (lfsr << 1) | bit; //shift LFSR left once and OR bit onto LFSR's LSB + lfsr &= 0xFFFFFF; //truncate lfsr to 24-bit + + } + + //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; + + //debug + //fprintf (stderr, "\nScrambler Key: 0x%06X; Seed: 0x%06X; Subtype: %02d; FN: %05d; ", key, lfsr, subtype, fn); + + return lfsr; +} + //scrambler pn sequence generation void scrambler_sequence_generator() { @@ -346,22 +384,23 @@ int main(int argc, char* argv[]) } parse_raw_key_string(key, argv[i+1]); - scrambler_seed = (key[0] << 16) | (key[1] << 8) | (key[2] << 0); + scrambler_key = (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); + scrambler_key = scrambler_key >> 16; + fprintf(stderr, "Scrambler key: 0x%02X (8-bit)\n", scrambler_key); } else if(length<=4) { - scrambler_seed = scrambler_seed >> 8; - fprintf(stderr, "Scrambler key: 0x%04X (16-bit)\n", scrambler_seed); + scrambler_key = scrambler_key >> 8; + fprintf(stderr, "Scrambler key: 0x%04X (16-bit)\n", scrambler_key); } else - fprintf(stderr, "Scrambler key: 0x%06X (24-bit)\n", scrambler_seed); + fprintf(stderr, "Scrambler key: 0x%06X (24-bit)\n", scrambler_key); encryption=1; //Scrambler key was passed + scrambler_seed = scrambler_key; //set initial seed value to key value } if(!strcmp(argv[i], "-l")) @@ -481,6 +520,8 @@ int main(int argc, char* argv[]) //Scrambler if (encryption == 1 && fn<0x7FFC) { + if ((fn % 0x8000)!=expected_next_fn) //frame skip, etc + scrambler_seed = scrambler_seed_calculation(scrambler_subtype, scrambler_key, fn&0x7FFF); scrambler_sequence_generator(); for(uint8_t i=0; i<16; i++) {