@@ -935,6 +935,114 @@ int k5_prepare(int fd) {
935935 return (1 );
936936}
937937
938+ #define CRC_POLY16 0x1021
939+ // slow bit-bang based
940+ // https://github.com/OneOfEleven/k5prog-win/blob/a8af838b91bf17027179881accc1701949d66a0b/Unit1.cpp#L1192C2-L1192C2
941+ uint16_t crc16 (const uint8_t * data , const int size )
942+ {
943+ uint16_t crc = 0 ;
944+ if (data != NULL && size > 0 )
945+ {
946+ for (int i = 0 ; i < size ; i ++ )
947+ {
948+ crc ^= (uint16_t )data [i ] << 8 ;
949+ for (unsigned int k = 8 ; k > 0 ; k -- )
950+ crc = (crc & 0x8000 ) ? (crc << 1 ) ^ CRC_POLY16 : crc << 1 ;
951+ }
952+ }
953+ return crc ;
954+ }
955+
956+ // (de)obfuscate firmware data
957+ // https://github.com/OneOfEleven/k5prog-win/blob/a8af838b91bf17027179881accc1701949d66a0b/Unit1.cpp#L1456
958+ void k5_xor_firmware (uint8_t * data , const int len )
959+ {
960+ static const uint8_t xor_pattern [] =
961+ {
962+ 0x47 , 0x22 , 0xc0 , 0x52 , 0x5d , 0x57 , 0x48 , 0x94 , 0xb1 , 0x60 , 0x60 , 0xdb , 0x6f , 0xe3 , 0x4c , 0x7c ,
963+ 0xd8 , 0x4a , 0xd6 , 0x8b , 0x30 , 0xec , 0x25 , 0xe0 , 0x4c , 0xd9 , 0x00 , 0x7f , 0xbf , 0xe3 , 0x54 , 0x05 ,
964+ 0xe9 , 0x3a , 0x97 , 0x6b , 0xb0 , 0x6e , 0x0c , 0xfb , 0xb1 , 0x1a , 0xe2 , 0xc9 , 0xc1 , 0x56 , 0x47 , 0xe9 ,
965+ 0xba , 0xf1 , 0x42 , 0xb6 , 0x67 , 0x5f , 0x0f , 0x96 , 0xf7 , 0xc9 , 0x3c , 0x84 , 0x1b , 0x26 , 0xe1 , 0x4e ,
966+ 0x3b , 0x6f , 0x66 , 0xe6 , 0xa0 , 0x6a , 0xb0 , 0xbf , 0xc6 , 0xa5 , 0x70 , 0x3a , 0xba , 0x18 , 0x9e , 0x27 ,
967+ 0x1a , 0x53 , 0x5b , 0x71 , 0xb1 , 0x94 , 0x1e , 0x18 , 0xf2 , 0xd6 , 0x81 , 0x02 , 0x22 , 0xfd , 0x5a , 0x28 ,
968+ 0x91 , 0xdb , 0xba , 0x5d , 0x64 , 0xc6 , 0xfe , 0x86 , 0x83 , 0x9c , 0x50 , 0x1c , 0x73 , 0x03 , 0x11 , 0xd6 ,
969+ 0xaf , 0x30 , 0xf4 , 0x2c , 0x77 , 0xb2 , 0x7d , 0xbb , 0x3f , 0x29 , 0x28 , 0x57 , 0x22 , 0xd6 , 0x92 , 0x8b
970+ };
971+
972+ if (data == NULL || len <= 0 )
973+ return ;
974+
975+ for (int i = 0 ; i < len ; i ++ )
976+ data [i ] ^= xor_pattern [i % sizeof (xor_pattern )];
977+ }
978+
979+ // https://github.com/OneOfEleven/k5prog-win/blob/a8af838b91bf17027179881accc1701949d66a0b/Unit1.cpp#L2663
980+ bool decrypt (char * flash , int * flash_size ) {
981+
982+ bool encrypted = true;
983+
984+ const uint16_t crc1 = crc16 (& flash [0 ], * flash_size - 2 );
985+ const uint16_t crc2 = ((uint16_t )flash [* flash_size - 1 ] << 8 ) | ((uint16_t )flash [* flash_size - 2 ] << 0 );
986+
987+ if (flash [ 2 ] == 0x00 &&
988+ flash [ 3 ] == 0x20 &&
989+ flash [ 6 ] == 0x00 &&
990+ flash [10 ] == 0x00 &&
991+ flash [14 ] == 0x00 ) {
992+ encrypted = false;
993+ }
994+
995+ if (encrypted && crc1 == crc2 )
996+ { // the file appears to be encrypted
997+
998+ // drop the 16-bit CRC
999+ * flash_size = * flash_size - 2 ;
1000+
1001+ // decrypt it
1002+ k5_xor_firmware (& flash [0 ], * flash_size );
1003+
1004+ if (flash [ 2 ] == 0x00 &&
1005+ flash [ 3 ] == 0x20 &&
1006+ flash [ 6 ] == 0x00 &&
1007+ flash [10 ] == 0x00 &&
1008+ flash [14 ] == 0x00 ) {
1009+ encrypted = false;
1010+ }
1011+
1012+ if (!encrypted )
1013+ {
1014+ fprintf (stdout , "firmware file de-obfuscated\n" );
1015+ }
1016+
1017+ if (!encrypted && * flash_size >= (0x2000 + 16 ))
1018+ { // extract and remove the 16-byte version string
1019+
1020+ char firmware_ver [17 ] = {0 };
1021+ memcpy (firmware_ver , & flash [0x2000 ], 16 );
1022+
1023+ if (* flash_size > (0x2000 + 16 ))
1024+ memmove (& flash [0x2000 ], & flash [0x2000 + 16 ], * flash_size - 0x2000 - 16 );
1025+ * flash_size = (* flash_size - 16 );
1026+
1027+ if (strlen (firmware_ver ) > 8 ) {
1028+ fprintf (stderr , "Firmware version unexpectedly long (%d): %s\n" , strlen (firmware_ver ), firmware_ver );
1029+ return false;
1030+ }
1031+ strncpy (flash_version_string , firmware_ver , 8 );
1032+
1033+ fprintf (stdout , "firmware file version '%s'\n" , flash_version_string );
1034+ }
1035+ }
1036+
1037+ if (encrypted )
1038+ {
1039+ fprintf (stderr ,"File doesn't appear to be valid for uploading\n" );
1040+ return false;
1041+ }
1042+
1043+ return true;
1044+ }
1045+
9381046int main (int argc ,char * * argv )
9391047{
9401048 int fd ,ffd ;
@@ -996,6 +1104,11 @@ int main(int argc,char **argv)
9961104 flash_length = read (ffd ,(unsigned char * )& flash ,UVK5_MAX_FLASH_SIZE );
9971105 close (ffd );
9981106
1107+ bool success = decrypt (flash , & flash_length );
1108+ if (!success ) {
1109+ exit (1 );
1110+ }
1111+
9991112 /* arbitrary limit do that someone doesn't flash some random short file */
10001113 if ((i_know_what_im_doing < 5 )&& (flash_length < 50000 )) {
10011114 fprintf (stderr ,"Failed to read whole eeprom from file %s (read %i), file too short or some other error\n" ,file ,flash_length );
0 commit comments