diff options
Diffstat (limited to 'utils/imxtools/sbtools')
-rw-r--r-- | utils/imxtools/sbtools/Makefile | 2 | ||||
-rw-r--r-- | utils/imxtools/sbtools/crypto.c | 1 | ||||
-rw-r--r-- | utils/imxtools/sbtools/crypto.h | 14 | ||||
-rw-r--r-- | utils/imxtools/sbtools/sb1.c | 288 | ||||
-rw-r--r-- | utils/imxtools/sbtools/sb1.h | 111 | ||||
-rw-r--r-- | utils/imxtools/sbtools/sbtoelf.c | 173 |
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 | ||
13 | sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o elf.o misc.o sb.o | 13 | sbtoelf: 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 | ||
16 | elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o | 16 | elftosb: 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 | ||
29 | static enum crypto_method_t cur_method = CRYPTO_NONE; | 29 | static enum crypto_method_t cur_method = CRYPTO_NONE; |
30 | static byte key[16]; | 30 | static byte key[16]; |
31 | static union xorcrypt_key_t xor_key[2]; | ||
31 | static uint16_t usb_vid, usb_pid; | 32 | static uint16_t usb_vid, usb_pid; |
32 | 33 | ||
33 | void crypto_setup(enum crypto_method_t method, void *param) | 34 | void 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 | ||
77 | union 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 */ |
77 | struct crypto_key_t | 84 | struct 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); | |||
112 | void sha_1_finish(struct sha_1_params_t *params); | 120 | void sha_1_finish(struct sha_1_params_t *params); |
113 | void sha_1_output(struct sha_1_params_t *params, byte *out); | 121 | void sha_1_output(struct sha_1_params_t *params, byte *out); |
114 | 122 | ||
123 | /* xorcrypt.c */ | ||
124 | |||
125 | // WARNING those functions modifies the keys !! | ||
126 | uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *data, int size); | ||
127 | uint32_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 | |||
29 | static uint16_t swap16(uint16_t t) | ||
30 | { | ||
31 | return (t << 8) | (t >> 8); | ||
32 | } | ||
33 | |||
34 | static 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 | |||
41 | enum sb1_error_t sb1_write_file(struct sb1_file_t *sb, const char *filename) | ||
42 | { | ||
43 | return SB1_ERROR; | ||
44 | } | ||
45 | |||
46 | struct 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 | |||
52 | struct 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 | |||
85 | static 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 | |||
99 | struct 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 *)§or[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 | |||
265 | void sb1_free(struct sb1_file_t *file) | ||
266 | { | ||
267 | if(!file) return; | ||
268 | |||
269 | free(file->data); | ||
270 | free(file); | ||
271 | } | ||
272 | |||
273 | void 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 */ | ||
32 | struct 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 | |||
42 | struct 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 | |||
55 | struct 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 | |||
74 | struct 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 | |||
82 | enum 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 | |||
96 | enum sb1_error_t sb1_write_file(struct sb1_file_t *sb, const char *filename); | ||
97 | |||
98 | typedef void (*sb1_color_printf)(void *u, bool err, color_t c, const char *f, ...); | ||
99 | struct 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 */ | ||
102 | struct 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); | ||
104 | struct sb1_file_t *sb1_read_memory(void *buffer, size_t size, void *u, | ||
105 | sb1_color_printf printf, enum sb1_error_t *err); | ||
106 | |||
107 | void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf printf); | ||
108 | void 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 | ||
160 | static 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 | |||
159 | static void usage(void) | 169 | static 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 | ||
206 | static 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 | |||
222 | enum sb_version_guess_t | ||
223 | { | ||
224 | SB_VERSION_1, | ||
225 | SB_VERSION_2, | ||
226 | SB_VERSION_UNK, | ||
227 | }; | ||
228 | |||
229 | enum 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 | |||
194 | int main(int argc, char **argv) | 260 | int 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; |