summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/samsungtools/Makefile5
-rw-r--r--utils/samsungtools/fwcrypt.c170
-rw-r--r--utils/samsungtools/samsung.c51
-rw-r--r--utils/samsungtools/samsung.h4
4 files changed, 229 insertions, 1 deletions
diff --git a/utils/samsungtools/Makefile b/utils/samsungtools/Makefile
index 97af8bb873..1179de5243 100644
--- a/utils/samsungtools/Makefile
+++ b/utils/samsungtools/Makefile
@@ -3,7 +3,7 @@ CC=gcc
3LD=gcc 3LD=gcc
4CFLAGS=-g -std=c99 -W -Wall $(DEFINES) `pkg-config --cflags openssl` 4CFLAGS=-g -std=c99 -W -Wall $(DEFINES) `pkg-config --cflags openssl`
5LDFLAGS=`pkg-config --libs openssl` 5LDFLAGS=`pkg-config --libs openssl`
6BINS=fwdecrypt 6BINS=fwdecrypt fwcrypt
7 7
8all: $(BINS) 8all: $(BINS)
9 9
@@ -13,5 +13,8 @@ all: $(BINS)
13fwdecrypt: fwdecrypt.o samsung.o 13fwdecrypt: fwdecrypt.o samsung.o
14 $(LD) -o $@ $^ $(LDFLAGS) 14 $(LD) -o $@ $^ $(LDFLAGS)
15 15
16fwcrypt: fwcrypt.o samsung.o
17 $(LD) -o $@ $^ $(LDFLAGS)
18
16clean: 19clean:
17 rm -fr *.o $(BINS) 20 rm -fr *.o $(BINS)
diff --git a/utils/samsungtools/fwcrypt.c b/utils/samsungtools/fwcrypt.c
new file mode 100644
index 0000000000..f920406e12
--- /dev/null
+++ b/utils/samsungtools/fwcrypt.c
@@ -0,0 +1,170 @@
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#include <string.h>
27
28static bool g_debug = false;
29static char *g_out_prefix = NULL;
30
31static void usage(void)
32{
33 printf("Usage: fwcrypt [options] content\n");
34 printf("Options:\n");
35 printf(" -o <prefix>\tSet output file\n");
36 printf(" -m/--model <model>\tSet model\n");
37 printf(" -v/--version <ver>\tSet version\n");
38 printf(" -r/--region <region>\tSet region\n");
39 printf(" -e/--extra <extra>\tSet extra\n");
40 printf(" -?/--help\tDisplay this message\n");
41 printf(" -d/--debug\tDisplay debug messages\n");
42 exit(1);
43}
44
45static int s_write(void *user, int offset, void *buf, int size)
46{
47 FILE *f = user;
48 if(fseek(f, offset, SEEK_SET) != 0)
49 return 0;
50 return fwrite(buf, 1, size, f);
51}
52
53static void s_printf(void *user, bool error, const char *fmt, ...)
54{
55 if(!g_debug && !error)
56 return;
57 (void) user;
58 va_list args;
59 va_start(args, fmt);
60 vprintf(fmt, args);
61 va_end(args);
62}
63
64int main(int argc, char **argv)
65{
66 struct samsung_firmware_t *fw = malloc(sizeof(struct samsung_firmware_t));
67 memset(fw, 0, sizeof(struct samsung_firmware_t));
68
69 if(argc <= 1)
70 usage();
71
72 while(1)
73 {
74 static struct option long_options[] =
75 {
76 {"help", no_argument, 0, '?'},
77 {"debug", no_argument, 0, 'd'},
78 {"model", required_argument, 0, 'm'},
79 {"version", required_argument, 0, 'v'},
80 {"region", required_argument, 0, 'r'},
81 {"extra", required_argument, 0, 'e'},
82 {0, 0, 0, 0}
83 };
84
85 int c = getopt_long(argc, argv, "?do:m:v:r:e:", long_options, NULL);
86 if(c == -1)
87 break;
88 switch(c)
89 {
90 case -1:
91 break;
92 case 'd':
93 g_debug = true;
94 break;
95 case '?':
96 usage();
97 break;
98 case 'o':
99 g_out_prefix = optarg;
100 break;
101 case 'm':
102 strncpy(fw->model, optarg, sizeof(fw->model));
103 if(strlen(optarg) > sizeof(fw->model))
104 printf("Warning: truncate model string\n");
105 break;
106 case 'r':
107 strncpy(fw->region, optarg, sizeof(fw->region));
108 if(strlen(optarg) > sizeof(fw->region))
109 printf("Warning: truncate region string\n");
110 break;
111 case 'v':
112 strncpy(fw->version, optarg, sizeof(fw->version));
113 if(strlen(optarg) > sizeof(fw->version))
114 printf("Warning: truncate vesion string\n");
115 break;
116 case 'e':
117 strncpy(fw->extra, optarg, sizeof(fw->extra));
118 if(strlen(optarg) > sizeof(fw->extra))
119 printf("Warning: truncate extra string\n");
120 break;
121 default:
122 abort();
123 }
124 }
125
126 if(optind != argc - 1)
127 usage();
128
129 FILE *fin = fopen(argv[optind], "rb");
130 if(fin == NULL)
131 {
132 printf("Cannot open file for reading: %m\n");
133 samsung_free(fw);
134 return 1;
135 }
136 fseek(fin, 0, SEEK_END);
137 fw->data_size = ftell(fin);
138 fseek(fin, 0, SEEK_SET);
139 fw->data = malloc(fw->data_size);
140 if((int)fread(fw->data, 1, fw->data_size, fin) != fw->data_size)
141 {
142 printf("Cannot read input file: %m\n");
143 samsung_free(fw);
144 return 2;
145 }
146 fclose(fin);
147
148 if(g_out_prefix)
149 {
150 FILE *f = fopen(g_out_prefix, "wb");
151 if(f == NULL)
152 {
153 printf("Cannot open file for writing: %m\n");
154 samsung_free(fw);
155 return 1;
156 }
157
158 enum samsung_error_t err = samsung_write(s_write, s_printf, f, fw);
159 if(err != SAMSUNG_SUCCESS)
160 {
161 printf("Error writing firmware: %d\n", err);
162 samsung_free(fw);
163 return 3;
164 }
165 fclose(f);
166 }
167 samsung_free(fw);
168
169 return 0;
170}
diff --git a/utils/samsungtools/samsung.c b/utils/samsungtools/samsung.c
index decf34f208..2d45b6f068 100644
--- a/utils/samsungtools/samsung.c
+++ b/utils/samsungtools/samsung.c
@@ -117,6 +117,57 @@ struct samsung_firmware_t *samsung_read(samsung_read_t read,
117 return fw; 117 return fw;
118} 118}
119 119
120enum samsung_error_t samsung_write(samsung_write_t write, samsung_printf_t printf,
121 void *user, struct samsung_firmware_t *fw)
122{
123 struct yp_header_t yp_hdr;
124 struct yp_md5_t yp_md5;
125
126 // write header
127 strncpy(yp_hdr.signature, YP_SIGNATURE, sizeof(yp_hdr.signature));
128 strncpy(yp_hdr.version, fw->version, sizeof(yp_hdr.version));
129 strncpy(yp_hdr.region, fw->region, sizeof(yp_hdr.region));
130 strncpy(yp_hdr.extra, fw->extra, sizeof(yp_hdr.extra));
131 strncpy(yp_hdr.model, fw->model, sizeof(yp_hdr.model));
132 yp_hdr.datasize = fw->data_size;
133
134 printf(user, false, "Model: %s\n", yp_hdr.model);
135 printf(user, false, "Version: %s %s %s\n", yp_hdr.version, yp_hdr.region, yp_hdr.extra);
136
137 if(write(user, 0, &yp_hdr, sizeof(yp_hdr)) != sizeof(yp_hdr))
138 {
139 printf(user, true, "Cannot write header\n");
140 return SAMSUNG_WRITE_ERROR;
141 }
142
143 // encrypt data
144 cyclic_xor(fw->data, fw->data_size, g_yp_key, sizeof(g_yp_key));
145 // compute MD5
146 MD5_CTX c;
147 MD5_Init(&c);
148 MD5_Update(&c, fw->data, fw->data_size);
149 MD5_Final(yp_md5.md5, &c);
150
151 // write data
152 if(write(user, sizeof(yp_hdr), fw->data, fw->data_size) != fw->data_size)
153 {
154 // decrypt data so that the firmware data is the same after the call
155 cyclic_xor(fw->data, fw->data_size, g_yp_key, sizeof(g_yp_key));
156 printf(user, true, "Cannot write data\n");
157 return SAMSUNG_WRITE_ERROR;
158 }
159 // decrypt data so that the firmware data is the same after the call
160 cyclic_xor(fw->data, fw->data_size, g_yp_key, sizeof(g_yp_key));
161 // write md5
162 if(write(user, sizeof(yp_hdr) + fw->data_size, &yp_md5, sizeof(yp_md5)) != sizeof(yp_md5))
163 {
164 printf(user, true, "Cannot write md5\n");
165 return SAMSUNG_WRITE_ERROR;
166 }
167
168 return SAMSUNG_SUCCESS;
169}
170
120void samsung_free(struct samsung_firmware_t *fw) 171void samsung_free(struct samsung_firmware_t *fw)
121{ 172{
122 if(fw) 173 if(fw)
diff --git a/utils/samsungtools/samsung.h b/utils/samsungtools/samsung.h
index 4336e02651..70ac9c770c 100644
--- a/utils/samsungtools/samsung.h
+++ b/utils/samsungtools/samsung.h
@@ -66,13 +66,17 @@ enum samsung_error_t
66 SAMSUNG_READ_ERROR = -1, 66 SAMSUNG_READ_ERROR = -1,
67 SAMSUNG_FORMAT_ERROR = -2, 67 SAMSUNG_FORMAT_ERROR = -2,
68 SAMSUNG_MD5_ERROR = -3, 68 SAMSUNG_MD5_ERROR = -3,
69 SAMSUNG_WRITE_ERROR = -4,
69}; 70};
70 71
71typedef int (*samsung_read_t)(void *user, int offset, void *buffer, int size); 72typedef int (*samsung_read_t)(void *user, int offset, void *buffer, int size);
73typedef int (*samsung_write_t)(void *user, int offset, void *buffer, int size);
72typedef void (*samsung_printf_t)(void *user, bool error, const char *fmt, ...); 74typedef void (*samsung_printf_t)(void *user, bool error, const char *fmt, ...);
73 75
74struct samsung_firmware_t *samsung_read(samsung_read_t read, 76struct samsung_firmware_t *samsung_read(samsung_read_t read,
75 samsung_printf_t printf, void *user, enum samsung_error_t *err); 77 samsung_printf_t printf, void *user, enum samsung_error_t *err);
78enum samsung_error_t samsung_write(samsung_write_t write, samsung_printf_t printf,
79 void *user, struct samsung_firmware_t *fw);
76void samsung_free(struct samsung_firmware_t *fw); 80void samsung_free(struct samsung_firmware_t *fw);
77 81
78#endif /* __SAMSUNG_H__ */ 82#endif /* __SAMSUNG_H__ */