A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd

Introduce samsungtools to decrypt samsung firmware

Samsung provides many firmware upgrade in the format of a .dat
file, at least for nearly all YP's (checked for Q2, R0, T10, Z5).
This is a simple cyclic xor which a fixed key, a md5 sum and a
header specifying the model/version/region.

Change-Id: Ib0461a74196383189fd2d8162da444a85a229c60

+353
+17
utils/samsungtools/Makefile
··· 1 + DEFINES= 2 + CC=gcc 3 + LD=gcc 4 + CFLAGS=-g -std=c99 -W -Wall $(DEFINES) `pkg-config --cflags openssl` 5 + LDFLAGS=`pkg-config --libs openssl` 6 + BINS=fwdecrypt 7 + 8 + all: $(BINS) 9 + 10 + %.o: %.c 11 + $(CC) $(CFLAGS) -c -o $@ $< 12 + 13 + fwdecrypt: fwdecrypt.o samsung.o 14 + $(LD) -o $@ $^ $(LDFLAGS) 15 + 16 + clean: 17 + rm -fr *.o $(BINS)
+131
utils/samsungtools/fwdecrypt.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2012 Amaury Pouly 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #include "samsung.h" 22 + #include <stdio.h> 23 + #include <stdlib.h> 24 + #include <stdarg.h> 25 + #include <getopt.h> 26 + 27 + static bool g_debug = false; 28 + static char *g_out_prefix = NULL; 29 + 30 + static void usage(void) 31 + { 32 + printf("Usage: fwdecrypt [options] firmware\n"); 33 + printf("Options:\n"); 34 + printf(" -o <prefix>\tSet output file\n"); 35 + printf(" -f/--force\tForce to continue on errors\n"); 36 + printf(" -?/--help\tDisplay this message\n"); 37 + printf(" -d/--debug\tDisplay debug messages\n"); 38 + exit(1); 39 + } 40 + 41 + static int s_read(void *user, int offset, void *buf, int size) 42 + { 43 + FILE *f = user; 44 + if(fseek(f, offset, SEEK_SET) != 0) 45 + return 0; 46 + return fread(buf, 1, size, f); 47 + } 48 + 49 + static void s_printf(void *user, bool error, const char *fmt, ...) 50 + { 51 + if(!g_debug && !error) 52 + return; 53 + (void) user; 54 + va_list args; 55 + va_start(args, fmt); 56 + vprintf(fmt, args); 57 + va_end(args); 58 + } 59 + 60 + int main(int argc, char **argv) 61 + { 62 + if(argc <= 1) 63 + usage(); 64 + 65 + while(1) 66 + { 67 + static struct option long_options[] = 68 + { 69 + {"help", no_argument, 0, '?'}, 70 + {"debug", no_argument, 0, 'd'}, 71 + {0, 0, 0, 0} 72 + }; 73 + 74 + int c = getopt_long(argc, argv, "?do:", long_options, NULL); 75 + if(c == -1) 76 + break; 77 + switch(c) 78 + { 79 + case -1: 80 + break; 81 + case 'd': 82 + g_debug = true; 83 + break; 84 + case '?': 85 + usage(); 86 + break; 87 + case 'o': 88 + g_out_prefix = optarg; 89 + break; 90 + default: 91 + abort(); 92 + } 93 + } 94 + 95 + if(optind != argc - 1) 96 + usage(); 97 + 98 + FILE *f = fopen(argv[optind], "rb"); 99 + if(f == NULL) 100 + { 101 + printf("Cannot open file for reading: %m\n"); 102 + return 1; 103 + } 104 + 105 + enum samsung_error_t err; 106 + struct samsung_firmware_t *fw = samsung_read(s_read, s_printf, 107 + f, &err); 108 + if(fw == NULL || err != SAMSUNG_SUCCESS) 109 + { 110 + printf("Error reading firmware: %d\n", err); 111 + samsung_free(fw); 112 + return 1; 113 + } 114 + fclose(f); 115 + 116 + if(g_out_prefix) 117 + { 118 + f = fopen(g_out_prefix, "wb"); 119 + if(f == NULL) 120 + { 121 + printf("Cannot open file for writing: %m\n"); 122 + return 2; 123 + } 124 + fwrite(fw->data, 1, fw->data_size, f); 125 + fclose(f); 126 + } 127 + 128 + samsung_free(fw); 129 + 130 + return 0; 131 + }
+127
utils/samsungtools/samsung.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2012 Amaury Pouly 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #include "samsung.h" 22 + #include <openssl/md5.h> 23 + #include <string.h> 24 + #include <stdlib.h> 25 + 26 + #ifndef MIN 27 + #define MIN(a,b) ((a) < (b) ? (a) : (b)) 28 + #endif 29 + 30 + static uint8_t g_yp_key[128] = 31 + { 32 + 0xa3, 0x04, 0xb9, 0xcd, 0x34, 0x13, 0x4a, 0x19, 0x19, 0x35, 0xdf, 0xbb, 0x8f, 0x3d, 0x7f, 0x09, 33 + 0x42, 0x3c, 0x96, 0xc6, 0x41, 0xa9, 0x95, 0xf1, 0xd0, 0xac, 0x16, 0x37, 0x57, 0x1f, 0x28, 0xe7, 34 + 0x0b, 0xc2, 0x12, 0x09, 0x39, 0x42, 0xd2, 0x96, 0xf5, 0x00, 0xd2, 0x23, 0xa4, 0x24, 0xe2, 0x8e, 35 + 0x50, 0x3c, 0x6e, 0x23, 0xeb, 0x68, 0xed, 0x31, 0xb7, 0xee, 0xc0, 0xc7, 0x09, 0xf8, 0x0e, 0x9d, 36 + 0x51, 0xed, 0x17, 0x95, 0x64, 0x09, 0xe0, 0xf9, 0xf0, 0xef, 0x86, 0xc0, 0x04, 0x46, 0x89, 0x8a, 37 + 0x6e, 0x27, 0x69, 0xde, 0xc7, 0x9d, 0x1e, 0xee, 0x3c, 0x3f, 0x17, 0x05, 0x44, 0xbb, 0xbb, 0x1d, 38 + 0x3d, 0x5d, 0x6e, 0xf2, 0xcf, 0x15, 0xd6, 0x3c, 0xcc, 0x7d, 0x67, 0x1a, 0xb8, 0xd2, 0x1b, 0x54, 39 + 0x97, 0xa2, 0x58, 0x58, 0xf7, 0x4e, 0x5e, 0x50, 0x42, 0x69, 0xdc, 0xe7, 0x3a, 0x87, 0x2e, 0x22 40 + }; 41 + 42 + static void cyclic_xor(void *data, int datasize, void *xor, int xorsize) 43 + { 44 + for(int i = 0; i < datasize; i++) 45 + *(uint8_t *)(data + i) ^= *(uint8_t *)(xor + (i % xorsize)); 46 + } 47 + 48 + struct samsung_firmware_t *samsung_read(samsung_read_t read, 49 + samsung_printf_t printf, void *user, enum samsung_error_t *err) 50 + { 51 + struct yp_header_t yp_hdr; 52 + struct yp_md5_t yp_md5; 53 + 54 + /* read and check header */ 55 + if(read(user, 0, &yp_hdr, sizeof(yp_hdr)) != sizeof(yp_hdr)) 56 + { 57 + printf(user, true, "Cannot read YP header\n"); 58 + *err = SAMSUNG_READ_ERROR; 59 + return NULL; 60 + } 61 + if(strncmp(yp_hdr.signature, YP_SIGNATURE, sizeof(yp_hdr.signature)) != 0) 62 + { 63 + printf(user, true, "Bad YP signature\n"); 64 + *err = SAMSUNG_FORMAT_ERROR; 65 + return NULL; 66 + } 67 + 68 + printf(user, false, "Model: %s\n", yp_hdr.model); 69 + printf(user, false, "Version: %s %s %s\n", yp_hdr.version, yp_hdr.region, yp_hdr.extra); 70 + 71 + /* allocate and read data */ 72 + struct samsung_firmware_t *fw = malloc(sizeof(struct samsung_firmware_t)); 73 + memset(fw, 0, sizeof(struct samsung_firmware_t)); 74 + fw->data_size = yp_hdr.datasize; 75 + fw->data = malloc(fw->data_size); 76 + strncpy(fw->version, yp_hdr.version, sizeof(yp_hdr.version)); 77 + strncpy(fw->region, yp_hdr.region, sizeof(yp_hdr.region)); 78 + strncpy(fw->extra, yp_hdr.extra, sizeof(yp_hdr.extra)); 79 + strncpy(fw->model, yp_hdr.model, sizeof(yp_hdr.model)); 80 + 81 + if(read(user, sizeof(yp_hdr), fw->data, fw->data_size) != fw->data_size) 82 + { 83 + printf(user, true, "Cannot read data\n"); 84 + *err = SAMSUNG_READ_ERROR; 85 + samsung_free(fw); 86 + return NULL; 87 + } 88 + 89 + /* read and check MD5 */ 90 + if(read(user, yp_hdr.datasize + sizeof(yp_hdr), &yp_md5, sizeof(yp_md5)) != sizeof(yp_md5)) 91 + { 92 + printf(user, true, "Cannot read MD5 sum\n"); 93 + *err = SAMSUNG_READ_ERROR; 94 + samsung_free(fw); 95 + return NULL; 96 + } 97 + 98 + uint8_t actual_md5[MD5_DIGEST_LENGTH]; 99 + MD5_CTX c; 100 + MD5_Init(&c); 101 + MD5_Update(&c, fw->data, fw->data_size); 102 + MD5_Final(actual_md5, &c); 103 + 104 + if(memcmp(actual_md5, yp_md5.md5, MD5_DIGEST_LENGTH) != 0) 105 + { 106 + printf(user, true, "MD5 mismatch\n"); 107 + *err = SAMSUNG_MD5_ERROR; 108 + samsung_free(fw); 109 + return NULL; 110 + } 111 + 112 + /* decrypt */ 113 + cyclic_xor(fw->data, fw->data_size, g_yp_key, sizeof(g_yp_key)); 114 + 115 + /* success ! */ 116 + *err = SAMSUNG_SUCCESS; 117 + return fw; 118 + } 119 + 120 + void samsung_free(struct samsung_firmware_t *fw) 121 + { 122 + if(fw) 123 + { 124 + free(fw->data); 125 + free(fw); 126 + } 127 + }
+78
utils/samsungtools/samsung.h
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2012 Amaury Pouly 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #ifndef __SAMSUNG_H__ 22 + #define __SAMSUNG_H__ 23 + 24 + #include <stdint.h> 25 + #include <stdbool.h> 26 + 27 + /** 28 + * Low-Level 29 + */ 30 + 31 + struct yp_header_t 32 + { 33 + char signature[12]; 34 + uint32_t pad; 35 + char version[8]; 36 + char region[4]; 37 + char extra[4]; 38 + char model[20]; 39 + uint32_t datasize; 40 + } __attribute__((packed)); 41 + 42 + struct yp_md5_t 43 + { 44 + uint8_t md5[16]; 45 + } __attribute__((packed)); 46 + 47 + #define YP_SIGNATURE "SAMSUNG YEPP" 48 + 49 + /** 50 + * API 51 + */ 52 + 53 + struct samsung_firmware_t 54 + { 55 + char version[8]; 56 + char region[4]; 57 + char extra[4]; 58 + char model[20]; 59 + void *data; 60 + int data_size; 61 + }; 62 + 63 + enum samsung_error_t 64 + { 65 + SAMSUNG_SUCCESS = 0, 66 + SAMSUNG_READ_ERROR = -1, 67 + SAMSUNG_FORMAT_ERROR = -2, 68 + SAMSUNG_MD5_ERROR = -3, 69 + }; 70 + 71 + typedef int (*samsung_read_t)(void *user, int offset, void *buffer, int size); 72 + typedef void (*samsung_printf_t)(void *user, bool error, const char *fmt, ...); 73 + 74 + struct samsung_firmware_t *samsung_read(samsung_read_t read, 75 + samsung_printf_t printf, void *user, enum samsung_error_t *err); 76 + void samsung_free(struct samsung_firmware_t *fw); 77 + 78 + #endif /* __SAMSUNG_H__ */