From c883e2bf0b8e20ecd2f7b54eafe0a68d9896a763 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sat, 20 Sep 2025 23:49:33 -0400 Subject: [PATCH] DMR: Tytera AP (PC4) Encryption Support Update to Allow 128-bit or 256-bit keys; --- .../cygwin_bat/complete_usage_options.txt | 3 +- src/crypt-tyt.c | 92 ++++++++++++++++--- src/dsd_main.c | 3 +- 3 files changed, 84 insertions(+), 14 deletions(-) diff --git a/examples/cygwin_bat/complete_usage_options.txt b/examples/cygwin_bat/complete_usage_options.txt index 0329fe4..8ff3818 100644 --- a/examples/cygwin_bat/complete_usage_options.txt +++ b/examples/cygwin_bat/complete_usage_options.txt @@ -172,9 +172,10 @@ Advanced Decoder options: -2 Manually Enter and Enforce TYT 16-bit BP Key Value (DMR) (Hex Value) - -! Manually Enter and Enforce TYT Advanced Privacy (PC4) AP Hex Key (see example below) + -! Manually Enter and Enforce TYT Advanced Privacy (PC4) 128 or 256 bit AP Hex Key (see example below) Encapulate in Single Quotation Marks; Space every 16 chars. -! '736B9A9C5645288B 243AD5CB8701EF8A' + -! '1111111111111111 1111111111111111 1111111111111111 1111111111111111' -@ Manually Enter and Enforce Retevis Advanced Privacy (RC2) 128 or 256 bit AP Hex Key (see example below) Encapulate in Single Quotation Marks; Space every 16 chars. diff --git a/src/crypt-tyt.c b/src/crypt-tyt.c index 2e56f60..e9c30db 100644 --- a/src/crypt-tyt.c +++ b/src/crypt-tyt.c @@ -159,28 +159,96 @@ void tyt16_ambe2_codeword_keystream(dsd_state * state, char ambe_fr[4][24], int void tyt_ap_pc4_keystream_creation(dsd_state * state, char * input) { - unsigned char key1[16] = {0}; - unsigned char key2[16] = {0}; - + unsigned char key1[64]; memset(key1, 0, sizeof(key1)); + unsigned char key2[64]; memset(key2, 0, sizeof(key2)); + char buf[1024]; strncpy(buf, input, sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; - + char *pEnd; uint64_t K1 = strtoull(buf, &pEnd, 16); uint64_t K2 = strtoull(pEnd, &pEnd, 16); + uint64_t K3 = strtoull(pEnd, &pEnd, 16); + uint64_t K4 = strtoull(pEnd, &pEnd, 16); + + if (K3 != 0 || K4 != 0) //256-bit keys loaded as ASCII characters + { + //start loading K1, K2, K3, and K4 as ASCII to fill 64 bytes of key1 + int k = 0; uint8_t x = 0; - u64_to_bytes_be(K1, &key1[0]); - u64_to_bytes_be(K2, &key1[8]); + for (int i = 0; i < 16; i++) + { + x = ((K1 >> (60-(i*4))) & 0xF); + if (x >= 0 && x <= 9) //numbers 0-9 + x += 0x30; //ASCII representation of numbers is 0x30, 0x31....0x39 + else x += 0x37; //Upper ASCII A,B,C,D,E,F is 0x41, 0x42...0x46 + key1[k++] = x; + } - for (int i=0;i<16;i++) key2[i] = key1[15-i]; + for (int i = 0; i < 16; i++) + { + x = ((K2 >> (60-(i*4))) & 0xF); + if (x >= 0 && x <= 9) //numbers 0-9 + x += 0x30; //ASCII representation of numbers is 0x30, 0x31....0x39 + else x += 0x37; //Upper ASCII A,B,C,D,E,F is 0x41, 0x42...0x46 + key1[k++] = x; + } - /* Create key schedule */ - create_keys(&ctx, key2, sizeof(key2)); - ctx.rounds = nbround; + for (int i = 0; i < 16; i++) + { + x = ((K3 >> (60-(i*4))) & 0xF); + if (x >= 0 && x <= 9) //numbers 0-9 + x += 0x30; //ASCII representation of numbers is 0x30, 0x31....0x39 + else x += 0x37; //Upper ASCII A,B,C,D,E,F is 0x41, 0x42...0x46 + key1[k++] = x; + } - fprintf (stderr,"DMR TYT AP (PC4) 128-bit Key %016llX%016llX with Forced Application\n", (unsigned long long int)K1, (unsigned long long int)K2); - state->tyt_ap = 1; + for (int i = 0; i < 16; i++) + { + x = ((K4 >> (60-(i*4))) & 0xF); + if (x >= 0 && x <= 9) //numbers 0-9 + x += 0x30; //ASCII representation of numbers is 0x30, 0x31....0x39 + else x += 0x37; //Upper ASCII A,B,C,D,E,F is 0x41, 0x42...0x46 + key1[k++] = x; + } + + //debug + // fprintf (stderr, "ASCII: "); + // for (int i = 0; i < 64; i++) + // fprintf (stderr, " %02X", key1[i]); + // fprintf (stderr, "\n"); + + /* Create key schedule */ + create_keys(&ctx, key1, 64); + ctx.rounds = nbround; + + fprintf(stderr, "DMR TYT AP (PC4) 256-bit Key %016llX%016llX%016llX%016llX with Forced Application\n", + (unsigned long long)K1, (unsigned long long)K2, (unsigned long long)K3, (unsigned long long)K4); + + state->tyt_ap = 1; + } + + else //128-bit loaded as reverse bytes + { + + u64_to_bytes_be(K1, &key1[0]); + u64_to_bytes_be(K2, &key1[8]); + + // reverse load the key bytes into key2 + for (int i=0;i<16;i++) + key2[i] = key1[15-i]; + + /* Create key schedule */ + create_keys(&ctx, key2, 16); + ctx.rounds = nbround; + + fprintf (stderr,"DMR TYT AP (PC4) 128-bit Key %016llX%016llX with Forced Application\n", + (unsigned long long int)K1, (unsigned long long int)K2); + + state->tyt_ap = 1; + } + } diff --git a/src/dsd_main.c b/src/dsd_main.c index 0b2a4d9..b64bcdb 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -1562,9 +1562,10 @@ printf (" \n"); printf (" -2 Manually Enter and Enforce TYT 16-bit BP Key Value (DMR) (Hex Value) \n"); printf (" \n"); - printf (" -! Manually Enter and Enforce TYT Advanced Privacy (PC4) AP Hex Key (see example below)\n"); + printf (" -! Manually Enter and Enforce TYT Advanced Privacy (PC4) 128 or 256 bit AP Hex Key (see example below)\n"); printf (" Encapulate in Single Quotation Marks; Space every 16 chars.\n"); printf (" -! '736B9A9C5645288B 243AD5CB8701EF8A' \n"); + printf (" -! '1111111111111111 1111111111111111 1111111111111111 1111111111111111' \n"); printf (" \n"); printf (" -@ Manually Enter and Enforce Retevis Advanced Privacy (RC2) 128 or 256 bit AP Hex Key (see example below)\n"); printf (" Encapulate in Single Quotation Marks; Space every 16 chars.\n");