summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-11-26 23:54:44 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2012-11-26 23:58:30 +0100
commit4e95b72ecbd972b9e1eb162c40a559b94eebac69 (patch)
tree2c71c5b9c07ba5758d6faadb93a7b2c7a252aa7d
parent33b7ade67f67e1358a60e68d5e2c6d8959acd45b (diff)
downloadrockbox-4e95b72ecbd972b9e1eb162c40a559b94eebac69.tar.gz
rockbox-4e95b72ecbd972b9e1eb162c40a559b94eebac69.zip
sbtools: add support for the stmp36xx format
The STMP36xx series also uses .sb files but with a different format. The main differences are the encryption and the lack of sections, making it basically a list of commands: fill, load, call, jump, switch mode, set sdram settings. Currently only the sbtoelf has support for the sb1 and can only dump the list of commands. Actual support for elf creation will come later. Change-Id: I1f2e0230c91ac64efd0e8430e0c5212098c599fd
-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;