summaryrefslogtreecommitdiff
path: root/utils/imxtools/sbtools
diff options
context:
space:
mode:
Diffstat (limited to 'utils/imxtools/sbtools')
-rw-r--r--utils/imxtools/sbtools/Makefile2
-rw-r--r--utils/imxtools/sbtools/crypto.c1
-rw-r--r--utils/imxtools/sbtools/crypto.h14
-rw-r--r--utils/imxtools/sbtools/sb1.c288
-rw-r--r--utils/imxtools/sbtools/sb1.h111
-rw-r--r--utils/imxtools/sbtools/sbtoelf.c173
6 files changed, 562 insertions, 27 deletions
diff --git a/utils/imxtools/sbtools/Makefile b/utils/imxtools/sbtools/Makefile
index 7a09d86d24..7d00e4b8c1 100644
--- a/utils/imxtools/sbtools/Makefile
+++ b/utils/imxtools/sbtools/Makefile
@@ -10,7 +10,7 @@ all: $(BINS)
10%.o: %.c 10%.o: %.c
11 $(CC) $(CFLAGS) -c -o $@ $< 11 $(CC) $(CFLAGS) -c -o $@ $<
12 12
13sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o elf.o misc.o sb.o 13sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o xorcrypt.o elf.o misc.o sb.o sb1.o
14 $(LD) -o $@ $^ $(LDFLAGS) 14 $(LD) -o $@ $^ $(LDFLAGS)
15 15
16elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o 16elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o
diff --git a/utils/imxtools/sbtools/crypto.c b/utils/imxtools/sbtools/crypto.c
index d4afc6c816..d73547de25 100644
--- a/utils/imxtools/sbtools/crypto.c
+++ b/utils/imxtools/sbtools/crypto.c
@@ -28,6 +28,7 @@
28 28
29static enum crypto_method_t cur_method = CRYPTO_NONE; 29static enum crypto_method_t cur_method = CRYPTO_NONE;
30static byte key[16]; 30static byte key[16];
31static union xorcrypt_key_t xor_key[2];
31static uint16_t usb_vid, usb_pid; 32static uint16_t usb_vid, usb_pid;
32 33
33void crypto_setup(enum crypto_method_t method, void *param) 34void crypto_setup(enum crypto_method_t method, void *param)
diff --git a/utils/imxtools/sbtools/crypto.h b/utils/imxtools/sbtools/crypto.h
index 452db6a28d..599ebf4bf4 100644
--- a/utils/imxtools/sbtools/crypto.h
+++ b/utils/imxtools/sbtools/crypto.h
@@ -47,6 +47,7 @@ enum crypto_method_t
47{ 47{
48 CRYPTO_NONE, /* disable */ 48 CRYPTO_NONE, /* disable */
49 CRYPTO_KEY, /* key */ 49 CRYPTO_KEY, /* key */
50 CRYPTO_XOR_KEY, /* XOR key */
50 CRYPTO_USBOTP, /* use usbotp device */ 51 CRYPTO_USBOTP, /* use usbotp device */
51}; 52};
52 53
@@ -73,6 +74,12 @@ int crypto_apply(
73 byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */ 74 byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
74 int encrypt); 75 int encrypt);
75 76
77union xorcrypt_key_t
78{
79 uint8_t key[64];
80 uint32_t k[16];
81};
82
76/* all-in-one function */ 83/* all-in-one function */
77struct crypto_key_t 84struct crypto_key_t
78{ 85{
@@ -80,6 +87,7 @@ struct crypto_key_t
80 union 87 union
81 { 88 {
82 byte key[16]; 89 byte key[16];
90 union xorcrypt_key_t xor_key[2];
83 uint32_t vid_pid; 91 uint32_t vid_pid;
84 byte param[0]; 92 byte param[0];
85 }u; 93 }u;
@@ -112,4 +120,10 @@ void sha_1_update(struct sha_1_params_t *params, byte *buffer, int size);
112void sha_1_finish(struct sha_1_params_t *params); 120void sha_1_finish(struct sha_1_params_t *params);
113void sha_1_output(struct sha_1_params_t *params, byte *out); 121void sha_1_output(struct sha_1_params_t *params, byte *out);
114 122
123/* xorcrypt.c */
124
125// WARNING those functions modifies the keys !!
126uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *data, int size);
127uint32_t xor_decrypt(union xorcrypt_key_t keys[2], void *data, int size);
128
115#endif /* __CRYPTO_H__ */ 129#endif /* __CRYPTO_H__ */
diff --git a/utils/imxtools/sbtools/sb1.c b/utils/imxtools/sbtools/sb1.c
new file mode 100644
index 0000000000..19f53b0015
--- /dev/null
+++ b/utils/imxtools/sbtools/sb1.c
@@ -0,0 +1,288 @@
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 <stdio.h>
22#include <time.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include "misc.h"
26#include "crypto.h"
27#include "sb1.h"
28
29static uint16_t swap16(uint16_t t)
30{
31 return (t << 8) | (t >> 8);
32}
33
34static void fix_version(struct sb1_version_t *ver)
35{
36 ver->major = swap16(ver->major);
37 ver->minor = swap16(ver->minor);
38 ver->revision = swap16(ver->revision);
39}
40
41enum sb1_error_t sb1_write_file(struct sb1_file_t *sb, const char *filename)
42{
43 return SB1_ERROR;
44}
45
46struct sb1_file_t *sb1_read_file(const char *filename, void *u,
47 sb1_color_printf cprintf, enum sb1_error_t *err)
48{
49 return sb1_read_file_ex(filename, 0, -1, u, cprintf, err);
50}
51
52struct sb1_file_t *sb1_read_file_ex(const char *filename, size_t offset, size_t size, void *u,
53 sb1_color_printf cprintf, enum sb1_error_t *err)
54{
55 #define fatal(e, ...) \
56 do { if(err) *err = e; \
57 cprintf(u, true, GREY, __VA_ARGS__); \
58 free(buf); \
59 return NULL; } while(0)
60
61 FILE *f = fopen(filename, "rb");
62 void *buf = NULL;
63 if(f == NULL)
64 fatal(SB1_OPEN_ERROR, "Cannot open file for reading\n");
65 fseek(f, 0, SEEK_END);
66 size_t read_size = ftell(f);
67 fseek(f, offset, SEEK_SET);
68 if(size != (size_t)-1)
69 read_size = size;
70 buf = xmalloc(read_size);
71 if(fread(buf, read_size, 1, f) != 1)
72 {
73 fclose(f);
74 fatal(SB1_READ_ERROR, "Cannot read file\n");
75 }
76 fclose(f);
77
78 struct sb1_file_t *ret = sb1_read_memory(buf, read_size, u, cprintf, err);
79 free(buf);
80 return ret;
81
82 #undef fatal
83}
84
85static const char *sb1_cmd_name(int cmd)
86{
87 switch(cmd)
88 {
89 case SB1_INST_LOAD: return "load";
90 case SB1_INST_FILL: return "fill";
91 case SB1_INST_JUMP: return "jump";
92 case SB1_INST_CALL: return "call";
93 case SB1_INST_MODE: return "mode";
94 case SB1_INST_SDRAM: return "sdram";
95 default: return "unknown";
96 }
97}
98
99struct sb1_file_t *sb1_read_memory(void *_buf, size_t filesize, void *u,
100 sb1_color_printf cprintf, enum sb1_error_t *err)
101{
102 struct sb1_file_t *sb1_file = NULL;
103 uint8_t *buf = _buf;
104
105 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
106 #define fatal(e, ...) \
107 do { if(err) *err = e; \
108 cprintf(u, true, GREY, __VA_ARGS__); \
109 sb1_free(sb1_file); \
110 return NULL; } while(0)
111 #define print_hex(c, p, len, nl) \
112 do { printf(c, ""); print_hex(p, len, nl); } while(0)
113
114 sb1_file = xmalloc(sizeof(struct sb1_file_t));
115 memset(sb1_file, 0, sizeof(struct sb1_file_t));
116 struct sb1_header_t *header = (struct sb1_header_t *)buf;
117
118 if(memcmp(header->signature, "STMP", 4) != 0)
119 fatal(SB1_FORMAT_ERROR, "Bad signature\n");
120 if(header->image_size > filesize)
121 fatal(SB1_FORMAT_ERROR, "File too small (should be at least %d bytes)\n",
122 header->image_size);
123 if(header->header_size != sizeof(struct sb1_header_t))
124 fatal(SB1_FORMAT_ERROR, "Bad header size\n");
125
126 printf(BLUE, "Basic info:\n");
127 printf(GREEN, " ROM version: ");
128 printf(YELLOW, "%x\n", header->rom_version);
129 printf(GREEN, " Userdata offset: ");
130 printf(YELLOW, "%x\n", header->userdata_offset);
131 printf(GREEN, " Pad: ");
132 printf(YELLOW, "%x\n", header->pad2);
133
134 struct sb1_version_t product_ver = header->product_ver;
135 fix_version(&product_ver);
136 struct sb1_version_t component_ver = header->component_ver;
137 fix_version(&component_ver);
138
139 memcpy(&sb1_file->product_ver, &product_ver, sizeof(product_ver));
140 memcpy(&sb1_file->component_ver, &component_ver, sizeof(component_ver));
141
142 printf(GREEN, " Product version: ");
143 printf(YELLOW, "%X.%X.%X\n", product_ver.major, product_ver.minor, product_ver.revision);
144 printf(GREEN, " Component version: ");
145 printf(YELLOW, "%X.%X.%X\n", component_ver.major, component_ver.minor, component_ver.revision);
146
147 printf(GREEN, " Drive tag: ");
148 printf(YELLOW, "%x\n", header->drive_tag);
149
150 /* reduce size w.r.t to userdata part */
151 uint32_t userdata_size = 0;
152 if(header->userdata_offset != 0)
153 {
154 userdata_size = header->image_size - header->userdata_offset;
155 header->image_size -= userdata_size;
156 }
157
158 if(header->image_size % SECTOR_SIZE)
159 {
160 if(g_force)
161 printf(GREY, "Image size is not a multiple of sector size\n");
162 else
163 fatal(SB1_FORMAT_ERROR, "Image size is not a multiple of sector size\n");
164 }
165
166 /* find key */
167 union xorcrypt_key_t key[2];
168 bool valid_key = false;
169 uint8_t sector[SECTOR_SIZE];
170
171 for(int i = 0; i < g_nr_keys; i++)
172 {
173 if(!g_key_array[i].method == CRYPTO_XOR_KEY)
174 continue;
175 /* copy key and data because it's modified by the crypto code */
176 memcpy(key, g_key_array[i].u.xor_key, sizeof(key));
177 memcpy(sector, header + 1, SECTOR_SIZE - header->header_size);
178 /* try to decrypt the first sector */
179 uint32_t mark = xor_decrypt(key, sector, SECTOR_SIZE - 4 - header->header_size);
180 if(mark != *(uint32_t *)&sector[SECTOR_SIZE - 4 - header->header_size])
181 continue;
182 /* found ! */
183 valid_key = true;
184 /* copy key again it's modified by the crypto code */
185 memcpy(key, g_key_array[i].u.xor_key, sizeof(key));
186 break;
187 }
188
189 printf(BLUE, "Crypto\n");
190 for(int i = 0; i < 2; i++)
191 {
192 printf(RED, " Key %d\n", i);
193 printf(OFF, " ");
194 for(int j = 0; j < 64; j++)
195 {
196 printf(YELLOW, "%02x ", key[i].key[j]);
197 if((j + 1) % 16 == 0)
198 {
199 printf(OFF, "\n");
200 if(j + 1 != 64)
201 printf(OFF, " ");
202 }
203 }
204 }
205
206 if(!valid_key)
207 fatal(SB1_NO_VALID_KEY, "No valid key found\n");
208
209 /* decrypt image in-place (and removing crypto markers) */
210 void *ptr = header + 1;
211 void *copy_ptr = header + 1;
212 int offset = header->header_size;
213 for(unsigned i = 0; i < header->image_size / SECTOR_SIZE; i++)
214 {
215 int size = SECTOR_SIZE - 4 - offset;
216 uint32_t mark = xor_decrypt(key, ptr, size);
217 if(mark != *(uint32_t *)(ptr + size))
218 fatal(SB1_CHECKSUM_ERROR, "Crypto mark mismatch\n");
219 memmove(copy_ptr, ptr, size);
220 ptr += size + 4;
221 copy_ptr += size;
222 offset = 0;
223 }
224
225 /* reduce image size given the removed marks */
226 header->image_size -= header->image_size / SECTOR_SIZE;
227
228 printf(BLUE, "Commands\n");
229 struct sb1_cmd_header_t *cmd = (void *)(header + 1);
230 while((void *)cmd < (void *)header + header->image_size)
231 {
232 printf(GREEN, " Command");
233 printf(YELLOW, " %#x\n", cmd->cmd);
234 printf(YELLOW, " Size:");
235 printf(RED, " %#x\n", SB1_CMD_SIZE(cmd->cmd));
236 printf(YELLOW, " Critical:");
237 printf(RED, " %d\n", SB1_CMD_CRITICAL(cmd->cmd));
238 printf(YELLOW, " Data Type:");
239 printf(RED, " %#x\n", SB1_CMD_DATATYPE(cmd->cmd));
240 printf(YELLOW, " Bytes:");
241 printf(RED, " %#x\n", SB1_CMD_BYTES(cmd->cmd));
242 printf(YELLOW, " Boot:");
243 printf(RED, " %#x (%s)\n", SB1_CMD_BOOT(cmd->cmd), sb1_cmd_name(SB1_CMD_BOOT(cmd->cmd)));
244 printf(YELLOW, " Addr:");
245 printf(RED, " %#x\n", cmd->addr);
246
247 /* last instruction ? */
248 if(SB1_CMD_BOOT(cmd->cmd) == SB1_INST_JUMP ||
249 SB1_CMD_BOOT(cmd->cmd) == SB1_INST_MODE)
250 break;
251
252 cmd = (void *)cmd + 4 + 4 * SB1_CMD_SIZE(cmd->cmd);
253 }
254
255 sb1_file->data_size = header->image_size - header->header_size;
256 sb1_file->data = malloc(sb1_file->data_size);
257 memcpy(sb1_file->data, header + 1, sb1_file->data_size);
258
259 return sb1_file;
260 #undef printf
261 #undef fatal
262 #undef print_hex
263}
264
265void sb1_free(struct sb1_file_t *file)
266{
267 if(!file) return;
268
269 free(file->data);
270 free(file);
271}
272
273void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf cprintf)
274{
275 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
276 #define print_hex(c, p, len, nl) \
277 do { printf(c, ""); print_hex(p, len, nl); } while(0)
278
279 #define TREE RED
280 #define HEADER GREEN
281 #define TEXT YELLOW
282 #define TEXT2 BLUE
283 #define SEP OFF
284
285 #undef printf
286 #undef print_hex
287}
288
diff --git a/utils/imxtools/sbtools/sb1.h b/utils/imxtools/sbtools/sb1.h
new file mode 100644
index 0000000000..f0a7a4ebc8
--- /dev/null
+++ b/utils/imxtools/sbtools/sb1.h
@@ -0,0 +1,111 @@
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 __SB1_H__
22#define __SB1_H__
23
24#include <stdint.h>
25#include <stdbool.h>
26
27#include "misc.h"
28
29#define SECTOR_SIZE 512
30
31/* All fields are in big-endian BCD */
32struct sb1_version_t
33{
34 uint16_t major;
35 uint16_t pad0;
36 uint16_t minor;
37 uint16_t pad1;
38 uint16_t revision;
39 uint16_t pad2;
40};
41
42struct sb1_header_t
43{
44 uint32_t rom_version;
45 uint32_t image_size;
46 uint32_t header_size;
47 uint32_t userdata_offset;
48 uint32_t pad2;
49 uint8_t signature[4]; /* Signature "STMP" */
50 struct sb1_version_t product_ver;
51 struct sb1_version_t component_ver;
52 uint32_t drive_tag;
53} __attribute__((packed));
54
55struct sb1_cmd_header_t
56{
57 uint32_t cmd; // 31:21=cmd size, 20=critical, 19:6=size 5:4=datatype, 3:0=boot cmd
58 uint32_t addr;
59} __attribute__((packed));
60
61#define SB1_CMD_SIZE(cmd) ((cmd) >> 21)
62#define SB1_CMD_CRITICAL(cmd) !!(cmd & (1 << 20))
63#define SB1_CMD_BYTES(cmd) (((cmd) >> 6) & 0x3fff)
64#define SB1_CMD_DATATYPE(cmd) (((cmd) >> 4) & 0x3)
65#define SB1_CMD_BOOT(cmd) ((cmd) & 0xf)
66
67#define SB1_INST_LOAD 0x1
68#define SB1_INST_FILL 0x2
69#define SB1_INST_JUMP 0x3
70#define SB1_INST_CALL 0x4
71#define SB1_INST_MODE 0x5
72#define SB1_INST_SDRAM 0x6
73
74struct sb1_file_t
75{
76 struct sb1_version_t product_ver;
77 struct sb1_version_t component_ver;
78 void *data;
79 int data_size;
80};
81
82enum sb1_error_t
83{
84 SB1_SUCCESS = 0,
85 SB1_ERROR = -1,
86 SB1_OPEN_ERROR = -2,
87 SB1_READ_ERROR = -3,
88 SB1_WRITE_ERROR = -4,
89 SB1_FORMAT_ERROR = -5,
90 SB1_CHECKSUM_ERROR = -6,
91 SB1_NO_VALID_KEY = -7,
92 SB1_FIRST_CRYPTO_ERROR = -8,
93 SB1_LAST_CRYPTO_ERROR = SB1_FIRST_CRYPTO_ERROR - CRYPTO_NUM_ERRORS,
94};
95
96enum sb1_error_t sb1_write_file(struct sb1_file_t *sb, const char *filename);
97
98typedef void (*sb1_color_printf)(void *u, bool err, color_t c, const char *f, ...);
99struct sb1_file_t *sb1_read_file(const char *filename, void *u,
100 sb1_color_printf printf, enum sb1_error_t *err);
101/* use size_t(-1) to use maximum size */
102struct sb1_file_t *sb1_read_file_ex(const char *filename, size_t offset, size_t size,
103 void *u, sb1_color_printf printf, enum sb1_error_t *err);
104struct sb1_file_t *sb1_read_memory(void *buffer, size_t size, void *u,
105 sb1_color_printf printf, enum sb1_error_t *err);
106
107void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf printf);
108void sb1_free(struct sb1_file_t *file);
109
110#endif /* __SB1_H__ */
111
diff --git a/utils/imxtools/sbtools/sbtoelf.c b/utils/imxtools/sbtools/sbtoelf.c
index 0170ea1836..0445c4a366 100644
--- a/utils/imxtools/sbtools/sbtoelf.c
+++ b/utils/imxtools/sbtools/sbtoelf.c
@@ -40,6 +40,7 @@
40#include "crypto.h" 40#include "crypto.h"
41#include "elf.h" 41#include "elf.h"
42#include "sb.h" 42#include "sb.h"
43#include "sb1.h"
43#include "misc.h" 44#include "misc.h"
44 45
45/* all blocks are sized as a multiple of 0x1ff */ 46/* all blocks are sized as a multiple of 0x1ff */
@@ -156,6 +157,15 @@ static void extract_sb_file(struct sb_file_t *file)
156 extract_sb_section(&file->sections[i]); 157 extract_sb_section(&file->sections[i]);
157} 158}
158 159
160static void extract_sb1_file(struct sb1_file_t *file)
161{
162 FILE *f = fopen(g_out_prefix, "wb");
163 if(f == NULL)
164 bugp("Cannot open %s for writing\n", g_out_prefix);
165 fwrite(file->data, file->data_size, 1, f);
166 fclose(f);
167}
168
159static void usage(void) 169static void usage(void)
160{ 170{
161 printf("Usage: sbtoelf [options] sb-file\n"); 171 printf("Usage: sbtoelf [options] sb-file\n");
@@ -170,6 +180,8 @@ static void usage(void)
170 printf(" -n/--no-color\tDisable output colors\n"); 180 printf(" -n/--no-color\tDisable output colors\n");
171 printf(" -l/--loopback <file>\tProduce sb file out of extracted description*\n"); 181 printf(" -l/--loopback <file>\tProduce sb file out of extracted description*\n");
172 printf(" -f/--force\tForce reading even without a key*\n"); 182 printf(" -f/--force\tForce reading even without a key*\n");
183 printf(" -1/--v1\tForce to read file as a version 1 file\n");
184 printf(" -2/--v2\tForce to read file as a version 2 file\n");
173 printf("Options marked with a * are for debug purpose only\n"); 185 printf("Options marked with a * are for debug purpose only\n");
174 exit(1); 186 exit(1);
175} 187}
@@ -191,11 +203,72 @@ static struct crypto_key_t g_zero_key =
191 .u.key = {0} 203 .u.key = {0}
192}; 204};
193 205
206static struct crypto_key_t g_default_xor_key =
207{
208 .method = CRYPTO_XOR_KEY,
209 .u.xor_key =
210 {
211 {.k = {0x67ECAEF6, 0xB31FB961, 0x118A9F4C, 0xA32A97DA,
212 0x6CC39617, 0x5BC00314, 0x9D430685, 0x4D7DB502,
213 0xA347685E, 0x3C87E86C, 0x8987AAA0, 0x24B78EF1,
214 0x893B9605, 0x9BB8C2BE, 0x6D9544E2, 0x375B525C}},
215 {.k = {0x3F424704, 0x53B5A331, 0x6AD345A5, 0x20DCEC51,
216 0x743C8D3B, 0x444B3792, 0x0AF429569, 0xB7EE1111,
217 0x583BF768, 0x9683BF9A, 0x0B032D799, 0xFE4E78ED,
218 0xF20D08C2, 0xFA0BE4A2, 0x4D89C317, 0x887B2D6F}}
219 }
220};
221
222enum sb_version_guess_t
223{
224 SB_VERSION_1,
225 SB_VERSION_2,
226 SB_VERSION_UNK,
227};
228
229enum sb_version_guess_t guess_sb_version(const char *filename)
230{
231 FILE *f = fopen(filename, "rb");
232 if(f == NULL)
233 bugp("Cannot open file for reading\n");
234 // check signature
235 uint8_t sig[4];
236 if(fseek(f, 20, SEEK_SET))
237 return SB_VERSION_UNK;
238 if(fread(sig, 4, 1, f) != 1)
239 return SB_VERSION_UNK;
240 if(memcmp(sig, "STMP", 4) != 0)
241 return SB_VERSION_UNK;
242 // check header size (v1)
243 uint32_t hdr_size;
244 if(fseek(f, 8, SEEK_SET))
245 return SB_VERSION_UNK;
246 if(fread(&hdr_size, 4, 1, f) != 1)
247 return SB_VERSION_UNK;
248 if(hdr_size == 0x34)
249 return SB_VERSION_1;
250 // check header size (v2)
251 if(fseek(f, 32, SEEK_SET))
252 return SB_VERSION_UNK;
253 if(fread(&hdr_size, 4, 1, f) != 1)
254 return SB_VERSION_UNK;
255 if(hdr_size == 0xc)
256 return SB_VERSION_2;
257 return SB_VERSION_UNK;
258}
259
194int main(int argc, char **argv) 260int main(int argc, char **argv)
195{ 261{
196 bool raw_mode = false; 262 bool raw_mode = false;
197 const char *loopback = NULL; 263 const char *loopback = NULL;
198 264 bool force_sb1 = false;
265 bool force_sb2 = false;
266
267 /* decrypt the xor key which is xor'ed */
268 for(int i = 0; i < 2; i++)
269 for(int j = 0; j < 16; j++)
270 g_default_xor_key.u.xor_key[i].k[j] ^= 0xaa55aa55;
271
199 while(1) 272 while(1)
200 { 273 {
201 static struct option long_options[] = 274 static struct option long_options[] =
@@ -205,11 +278,13 @@ int main(int argc, char **argv)
205 {"add-key", required_argument, 0, 'a'}, 278 {"add-key", required_argument, 0, 'a'},
206 {"no-color", no_argument, 0, 'n'}, 279 {"no-color", no_argument, 0, 'n'},
207 {"loopback", required_argument, 0, 'l'}, 280 {"loopback", required_argument, 0, 'l'},
208 {"force", no_argument, 0, 'f' }, 281 {"force", no_argument, 0, 'f'},
282 {"v1", no_argument, 0, '1'},
283 {"v2", no_argument, 0, '2'},
209 {0, 0, 0, 0} 284 {0, 0, 0, 0}
210 }; 285 };
211 286
212 int c = getopt_long(argc, argv, "?do:k:zra:nl:f", long_options, NULL); 287 int c = getopt_long(argc, argv, "?do:k:zra:nl:f12x", long_options, NULL);
213 if(c == -1) 288 if(c == -1)
214 break; 289 break;
215 switch(c) 290 switch(c)
@@ -243,10 +318,11 @@ int main(int argc, char **argv)
243 break; 318 break;
244 } 319 }
245 case 'z': 320 case 'z':
246 {
247 add_keys(&g_zero_key, 1); 321 add_keys(&g_zero_key, 1);
248 break; 322 break;
249 } 323 case 'x':
324 add_keys(&g_default_xor_key, 1);
325 break;
250 case 'r': 326 case 'r':
251 raw_mode = true; 327 raw_mode = true;
252 break; 328 break;
@@ -261,11 +337,20 @@ int main(int argc, char **argv)
261 add_keys(&key, 1); 337 add_keys(&key, 1);
262 break; 338 break;
263 } 339 }
340 case '1':
341 force_sb1 = true;
342 break;
343 case '2':
344 force_sb2 = true;
345 break;
264 default: 346 default:
265 abort(); 347 abort();
266 } 348 }
267 } 349 }
268 350
351 if(force_sb1 && force_sb2)
352 bug("You cannot force both version 1 and 2\n");
353
269 if(argc - optind != 1) 354 if(argc - optind != 1)
270 { 355 {
271 usage(); 356 usage();
@@ -274,34 +359,70 @@ int main(int argc, char **argv)
274 359
275 const char *sb_filename = argv[optind]; 360 const char *sb_filename = argv[optind];
276 361
277 enum sb_error_t err; 362 enum sb_version_guess_t ver = guess_sb_version(sb_filename);
278 struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf, &err); 363
279 if(file == NULL) 364 if(force_sb2 || ver == SB_VERSION_2)
280 { 365 {
366 enum sb_error_t err;
367 struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf, &err);
368 if(file == NULL)
369 {
370 color(OFF);
371 printf("SB read failed: %d\n", err);
372 return 1;
373 }
374
281 color(OFF); 375 color(OFF);
282 printf("SB read failed: %d\n", err); 376 if(g_out_prefix)
283 return 1; 377 extract_sb_file(file);
378 if(g_debug)
379 {
380 color(GREY);
381 printf("[Debug output]\n");
382 sb_dump(file, NULL, sb_printf);
383 }
384 if(loopback)
385 {
386 /* sb_read_file will fill real key and IV but we don't want to override
387 * them when looping back otherwise the output will be inconsistent and
388 * garbage */
389 file->override_real_key = false;
390 file->override_crypto_iv = false;
391 sb_write_file(file, loopback);
392 }
393 sb_free(file);
284 } 394 }
285 395 else if(force_sb1 || ver == SB_VERSION_1)
286 color(OFF);
287 if(g_out_prefix)
288 extract_sb_file(file);
289 if(g_debug)
290 { 396 {
291 color(GREY); 397 enum sb1_error_t err;
292 printf("[Debug output]\n"); 398 struct sb1_file_t *file = sb1_read_file(sb_filename, NULL, sb_printf, &err);
293 sb_dump(file, NULL, sb_printf); 399 if(file == NULL)
400 {
401 color(OFF);
402 printf("SB read failed: %d\n", err);
403 return 1;
404 }
405
406 color(OFF);
407 if(g_out_prefix)
408 extract_sb1_file(file);
409 if(g_debug)
410 {
411 color(GREY);
412 printf("[Debug output]\n");
413 sb1_dump(file, NULL, sb_printf);
414 }
415 if(loopback)
416 sb1_write_file(file, loopback);
417
418 sb1_free(file);
294 } 419 }
295 if(loopback) 420 else
296 { 421 {
297 /* sb_read_file will fill real key and IV but we don't want to override 422 color(OFF);
298 * them when looping back otherwise the output will be inconsistent and 423 printf("Cannot guess file type, are you sure it's a valid image ?\n");
299 * garbage */ 424 return 1;
300 file->override_real_key = false;
301 file->override_crypto_iv = false;
302 sb_write_file(file, loopback);
303 } 425 }
304 sb_free(file);
305 clear_keys(); 426 clear_keys();
306 427
307 return 0; 428 return 0;