summaryrefslogtreecommitdiffstats
path: root/utils
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 /utils
parent33b7ade67f67e1358a60e68d5e2c6d8959acd45b (diff)
downloadrockbox-4e95b72ecbd972b9e1eb162c40a559b94eebac69.tar.gz
rockbox-4e95b72ecbd972b9e1eb162c40a559b94eebac69.tar.bz2
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
Diffstat (limited to 'utils')
-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)
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
-sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o elf.o misc.o sb.o
+sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o xorcrypt.o elf.o misc.o sb.o sb1.o
$(LD) -o $@ $^ $(LDFLAGS)
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 @@
static enum crypto_method_t cur_method = CRYPTO_NONE;
static byte key[16];
+static union xorcrypt_key_t xor_key[2];
static uint16_t usb_vid, usb_pid;
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
{
CRYPTO_NONE, /* disable */
CRYPTO_KEY, /* key */
+ CRYPTO_XOR_KEY, /* XOR key */
CRYPTO_USBOTP, /* use usbotp device */
};
@@ -73,6 +74,12 @@ int crypto_apply(
byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
int encrypt);
+union xorcrypt_key_t
+{
+ uint8_t key[64];
+ uint32_t k[16];
+};
+
/* all-in-one function */
struct crypto_key_t
{
@@ -80,6 +87,7 @@ struct crypto_key_t
union
{
byte key[16];
+ union xorcrypt_key_t xor_key[2];
uint32_t vid_pid;
byte param[0];
}u;
@@ -112,4 +120,10 @@ void sha_1_update(struct sha_1_params_t *params, byte *buffer, int size);
void sha_1_finish(struct sha_1_params_t *params);
void sha_1_output(struct sha_1_params_t *params, byte *out);
+/* xorcrypt.c */
+
+// WARNING those functions modifies the keys !!
+uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *data, int size);
+uint32_t xor_decrypt(union xorcrypt_key_t keys[2], void *data, int size);
+
#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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2012 Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "misc.h"
+#include "crypto.h"
+#include "sb1.h"
+
+static uint16_t swap16(uint16_t t)
+{
+ return (t << 8) | (t >> 8);
+}
+
+static void fix_version(struct sb1_version_t *ver)
+{
+ ver->major = swap16(ver->major);
+ ver->minor = swap16(ver->minor);
+ ver->revision = swap16(ver->revision);
+}
+
+enum sb1_error_t sb1_write_file(struct sb1_file_t *sb, const char *filename)
+{
+ return SB1_ERROR;
+}
+
+struct sb1_file_t *sb1_read_file(const char *filename, void *u,
+ sb1_color_printf cprintf, enum sb1_error_t *err)
+{
+ return sb1_read_file_ex(filename, 0, -1, u, cprintf, err);
+}
+
+struct sb1_file_t *sb1_read_file_ex(const char *filename, size_t offset, size_t size, void *u,
+ sb1_color_printf cprintf, enum sb1_error_t *err)
+{
+ #define fatal(e, ...) \
+ do { if(err) *err = e; \
+ cprintf(u, true, GREY, __VA_ARGS__); \
+ free(buf); \
+ return NULL; } while(0)
+
+ FILE *f = fopen(filename, "rb");
+ void *buf = NULL;
+ if(f == NULL)
+ fatal(SB1_OPEN_ERROR, "Cannot open file for reading\n");
+ fseek(f, 0, SEEK_END);
+ size_t read_size = ftell(f);
+ fseek(f, offset, SEEK_SET);
+ if(size != (size_t)-1)
+ read_size = size;
+ buf = xmalloc(read_size);
+ if(fread(buf, read_size, 1, f) != 1)
+ {
+ fclose(f);
+ fatal(SB1_READ_ERROR, "Cannot read file\n");
+ }
+ fclose(f);
+
+ struct sb1_file_t *ret = sb1_read_memory(buf, read_size, u, cprintf, err);
+ free(buf);
+ return ret;
+
+ #undef fatal
+}
+
+static const char *sb1_cmd_name(int cmd)
+{
+ switch(cmd)
+ {
+ case SB1_INST_LOAD: return "load";
+ case SB1_INST_FILL: return "fill";
+ case SB1_INST_JUMP: return "jump";
+ case SB1_INST_CALL: return "call";
+ case SB1_INST_MODE: return "mode";
+ case SB1_INST_SDRAM: return "sdram";
+ default: return "unknown";
+ }
+}
+
+struct sb1_file_t *sb1_read_memory(void *_buf, size_t filesize, void *u,
+ sb1_color_printf cprintf, enum sb1_error_t *err)
+{
+ struct sb1_file_t *sb1_file = NULL;
+ uint8_t *buf = _buf;
+
+ #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
+ #define fatal(e, ...) \
+ do { if(err) *err = e; \
+ cprintf(u, true, GREY, __VA_ARGS__); \
+ sb1_free(sb1_file); \
+ return NULL; } while(0)
+ #define print_hex(c, p, len, nl) \
+ do { printf(c, ""); print_hex(p, len, nl); } while(0)
+
+ sb1_file = xmalloc(sizeof(struct sb1_file_t));
+ memset(sb1_file, 0, sizeof(struct sb1_file_t));
+ struct sb1_header_t *header = (struct sb1_header_t *)buf;
+
+ if(memcmp(header->signature, "STMP", 4) != 0)
+ fatal(SB1_FORMAT_ERROR, "Bad signature\n");
+ if(header->image_size > filesize)
+ fatal(SB1_FORMAT_ERROR, "File too small (should be at least %d bytes)\n",
+ header->image_size);
+ if(header->header_size != sizeof(struct sb1_header_t))
+ fatal(SB1_FORMAT_ERROR, "Bad header size\n");
+
+ printf(BLUE, "Basic info:\n");
+ printf(GREEN, " ROM version: ");
+ printf(YELLOW, "%x\n", header->rom_version);
+ printf(GREEN, " Userdata offset: ");
+ printf(YELLOW, "%x\n", header->userdata_offset);
+ printf(GREEN, " Pad: ");
+ printf(YELLOW, "%x\n", header->pad2);
+
+ struct sb1_version_t product_ver = header->product_ver;
+ fix_version(&product_ver);
+ struct sb1_version_t component_ver = header->component_ver;
+ fix_version(&component_ver);
+
+ memcpy(&sb1_file->product_ver, &product_ver, sizeof(product_ver));
+ memcpy(&sb1_file->component_ver, &component_ver, sizeof(component_ver));
+
+ printf(GREEN, " Product version: ");
+ printf(YELLOW, "%X.%X.%X\n", product_ver.major, product_ver.minor, product_ver.revision);
+ printf(GREEN, " Component version: ");
+ printf(YELLOW, "%X.%X.%X\n", component_ver.major, component_ver.minor, component_ver.revision);
+
+ printf(GREEN, " Drive tag: ");
+ printf(YELLOW, "%x\n", header->drive_tag);
+
+ /* reduce size w.r.t to userdata part */
+ uint32_t userdata_size = 0;
+ if(header->userdata_offset != 0)
+ {
+ userdata_size = header->image_size - header->userdata_offset;
+ header->image_size -= userdata_size;
+ }
+
+ if(header->image_size % SECTOR_SIZE)
+ {
+ if(g_force)
+ printf(GREY, "Image size is not a multiple of sector size\n");
+ else
+ fatal(SB1_FORMAT_ERROR, "Image size is not a multiple of sector size\n");
+ }
+
+ /* find key */
+ union xorcrypt_key_t key[2];
+ bool valid_key = false;
+ uint8_t sector[SECTOR_SIZE];
+
+ for(int i = 0; i < g_nr_keys; i++)
+ {
+ if(!g_key_array[i].method == CRYPTO_XOR_KEY)
+ continue;
+ /* copy key and data because it's modified by the crypto code */
+ memcpy(key, g_key_array[i].u.xor_key, sizeof(key));
+ memcpy(sector, header + 1, SECTOR_SIZE - header->header_size);
+ /* try to decrypt the first sector */
+ uint32_t mark = xor_decrypt(key, sector, SECTOR_SIZE - 4 - header->header_size);
+ if(mark != *(uint32_t *)&sector[SECTOR_SIZE - 4 - header->header_size])
+ continue;
+ /* found ! */
+ valid_key = true;
+ /* copy key again it's modified by the crypto code */
+ memcpy(key, g_key_array[i].u.xor_key, sizeof(key));
+ break;
+ }
+
+ printf(BLUE, "Crypto\n");
+ for(int i = 0; i < 2; i++)
+ {
+ printf(RED, " Key %d\n", i);
+ printf(OFF, " ");
+ for(int j = 0; j < 64; j++)
+ {
+ printf(YELLOW, "%02x ", key[i].key[j]);
+ if((j + 1) % 16 == 0)
+ {
+ printf(OFF, "\n");
+ if(j + 1 != 64)
+ printf(OFF, " ");
+ }
+ }
+ }
+
+ if(!valid_key)
+ fatal(SB1_NO_VALID_KEY, "No valid key found\n");
+
+ /* decrypt image in-place (and removing crypto markers) */
+ void *ptr = header + 1;
+ void *copy_ptr = header + 1;
+ int offset = header->header_size;
+ for(unsigned i = 0; i < header->image_size / SECTOR_SIZE; i++)
+ {
+ int size = SECTOR_SIZE - 4 - offset;
+ uint32_t mark = xor_decrypt(key, ptr, size);
+ if(mark != *(uint32_t *)(ptr + size))
+ fatal(SB1_CHECKSUM_ERROR, "Crypto mark mismatch\n");
+ memmove(copy_ptr, ptr, size);
+ ptr += size + 4;
+ copy_ptr += size;
+ offset = 0;
+ }
+
+ /* reduce image size given the removed marks */
+ header->image_size -= header->image_size / SECTOR_SIZE;
+
+ printf(BLUE, "Commands\n");
+ struct sb1_cmd_header_t *cmd = (void *)(header + 1);
+ while((void *)cmd < (void *)header + header->image_size)
+ {
+ printf(GREEN, " Command");
+ printf(YELLOW, " %#x\n", cmd->cmd);
+ printf(YELLOW, " Size:");
+ printf(RED, " %#x\n", SB1_CMD_SIZE(cmd->cmd));
+ printf(YELLOW, " Critical:");
+ printf(RED, " %d\n", SB1_CMD_CRITICAL(cmd->cmd));
+ printf(YELLOW, " Data Type:");
+ printf(RED, " %#x\n", SB1_CMD_DATATYPE(cmd->cmd));
+ printf(YELLOW, " Bytes:");
+ printf(RED, " %#x\n", SB1_CMD_BYTES(cmd->cmd));
+ printf(YELLOW, " Boot:");
+ printf(RED, " %#x (%s)\n", SB1_CMD_BOOT(cmd->cmd), sb1_cmd_name(SB1_CMD_BOOT(cmd->cmd)));
+ printf(YELLOW, " Addr:");
+ printf(RED, " %#x\n", cmd->addr);
+
+ /* last instruction ? */
+ if(SB1_CMD_BOOT(cmd->cmd) == SB1_INST_JUMP ||
+ SB1_CMD_BOOT(cmd->cmd) == SB1_INST_MODE)
+ break;
+
+ cmd = (void *)cmd + 4 + 4 * SB1_CMD_SIZE(cmd->cmd);
+ }
+
+ sb1_file->data_size = header->image_size - header->header_size;
+ sb1_file->data = malloc(sb1_file->data_size);
+ memcpy(sb1_file->data, header + 1, sb1_file->data_size);
+
+ return sb1_file;
+ #undef printf
+ #undef fatal
+ #undef print_hex
+}
+
+void sb1_free(struct sb1_file_t *file)
+{
+ if(!file) return;
+
+ free(file->data);
+ free(file);
+}
+
+void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf cprintf)
+{
+ #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
+ #define print_hex(c, p, len, nl) \
+ do { printf(c, ""); print_hex(p, len, nl); } while(0)
+
+ #define TREE RED
+ #define HEADER GREEN
+ #define TEXT YELLOW
+ #define TEXT2 BLUE
+ #define SEP OFF
+
+ #undef printf
+ #undef print_hex
+}
+
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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2012 Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __SB1_H__
+#define __SB1_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "misc.h"
+
+#define SECTOR_SIZE 512
+
+/* All fields are in big-endian BCD */
+struct sb1_version_t
+{
+ uint16_t major;
+ uint16_t pad0;
+ uint16_t minor;
+ uint16_t pad1;
+ uint16_t revision;
+ uint16_t pad2;
+};
+
+struct sb1_header_t
+{
+ uint32_t rom_version;
+ uint32_t image_size;
+ uint32_t header_size;
+ uint32_t userdata_offset;
+ uint32_t pad2;
+ uint8_t signature[4]; /* Signature "STMP" */
+ struct sb1_version_t product_ver;
+ struct sb1_version_t component_ver;
+ uint32_t drive_tag;
+} __attribute__((packed));
+
+struct sb1_cmd_header_t
+{
+ uint32_t cmd; // 31:21=cmd size, 20=critical, 19:6=size 5:4=datatype, 3:0=boot cmd
+ uint32_t addr;
+} __attribute__((packed));
+
+#define SB1_CMD_SIZE(cmd) ((cmd) >> 21)
+#define SB1_CMD_CRITICAL(cmd) !!(cmd & (1 << 20))
+#define SB1_CMD_BYTES(cmd) (((cmd) >> 6) & 0x3fff)
+#define SB1_CMD_DATATYPE(cmd) (((cmd) >> 4) & 0x3)
+#define SB1_CMD_BOOT(cmd) ((cmd) & 0xf)
+
+#define SB1_INST_LOAD 0x1
+#define SB1_INST_FILL 0x2
+#define SB1_INST_JUMP 0x3
+#define SB1_INST_CALL 0x4
+#define SB1_INST_MODE 0x5
+#define SB1_INST_SDRAM 0x6
+
+struct sb1_file_t
+{
+ struct sb1_version_t product_ver;
+ struct sb1_version_t component_ver;
+ void *data;
+ int data_size;
+};
+
+enum sb1_error_t
+{
+ SB1_SUCCESS = 0,
+ SB1_ERROR = -1,
+ SB1_OPEN_ERROR = -2,
+ SB1_READ_ERROR = -3,
+ SB1_WRITE_ERROR = -4,
+ SB1_FORMAT_ERROR = -5,
+ SB1_CHECKSUM_ERROR = -6,
+ SB1_NO_VALID_KEY = -7,
+ SB1_FIRST_CRYPTO_ERROR = -8,
+ SB1_LAST_CRYPTO_ERROR = SB1_FIRST_CRYPTO_ERROR - CRYPTO_NUM_ERRORS,
+};
+
+enum sb1_error_t sb1_write_file(struct sb1_file_t *sb, const char *filename);
+
+typedef void (*sb1_color_printf)(void *u, bool err, color_t c, const char *f, ...);
+struct sb1_file_t *sb1_read_file(const char *filename, void *u,
+ sb1_color_printf printf, enum sb1_error_t *err);
+/* use size_t(-1) to use maximum size */
+struct sb1_file_t *sb1_read_file_ex(const char *filename, size_t offset, size_t size,
+ void *u, sb1_color_printf printf, enum sb1_error_t *err);
+struct sb1_file_t *sb1_read_memory(void *buffer, size_t size, void *u,
+ sb1_color_printf printf, enum sb1_error_t *err);
+
+void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf printf);
+void sb1_free(struct sb1_file_t *file);
+
+#endif /* __SB1_H__ */
+
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 @@
#include "crypto.h"
#include "elf.h"
#include "sb.h"
+#include "sb1.h"
#include "misc.h"
/* all blocks are sized as a multiple of 0x1ff */
@@ -156,6 +157,15 @@ static void extract_sb_file(struct sb_file_t *file)
extract_sb_section(&file->sections[i]);
}
+static void extract_sb1_file(struct sb1_file_t *file)
+{
+ FILE *f = fopen(g_out_prefix, "wb");
+ if(f == NULL)
+ bugp("Cannot open %s for writing\n", g_out_prefix);
+ fwrite(file->data, file->data_size, 1, f);
+ fclose(f);
+}
+
static void usage(void)
{
printf("Usage: sbtoelf [options] sb-file\n");
@@ -170,6 +180,8 @@ static void usage(void)
printf(" -n/--no-color\tDisable output colors\n");
printf(" -l/--loopback <file>\tProduce sb file out of extracted description*\n");
printf(" -f/--force\tForce reading even without a key*\n");
+ printf(" -1/--v1\tForce to read file as a version 1 file\n");
+ printf(" -2/--v2\tForce to read file as a version 2 file\n");
printf("Options marked with a * are for debug purpose only\n");
exit(1);
}
@@ -191,11 +203,72 @@ static struct crypto_key_t g_zero_key =
.u.key = {0}
};
+static struct crypto_key_t g_default_xor_key =
+{
+ .method = CRYPTO_XOR_KEY,
+ .u.xor_key =
+ {
+ {.k = {0x67ECAEF6, 0xB31FB961, 0x118A9F4C, 0xA32A97DA,
+ 0x6CC39617, 0x5BC00314, 0x9D430685, 0x4D7DB502,
+ 0xA347685E, 0x3C87E86C, 0x8987AAA0, 0x24B78EF1,
+ 0x893B9605, 0x9BB8C2BE, 0x6D9544E2, 0x375B525C}},
+ {.k = {0x3F424704, 0x53B5A331, 0x6AD345A5, 0x20DCEC51,
+ 0x743C8D3B, 0x444B3792, 0x0AF429569, 0xB7EE1111,
+ 0x583BF768, 0x9683BF9A, 0x0B032D799, 0xFE4E78ED,
+ 0xF20D08C2, 0xFA0BE4A2, 0x4D89C317, 0x887B2D6F}}
+ }
+};
+
+enum sb_version_guess_t
+{
+ SB_VERSION_1,
+ SB_VERSION_2,
+ SB_VERSION_UNK,
+};
+
+enum sb_version_guess_t guess_sb_version(const char *filename)
+{
+ FILE *f = fopen(filename, "rb");
+ if(f == NULL)
+ bugp("Cannot open file for reading\n");
+ // check signature
+ uint8_t sig[4];
+ if(fseek(f, 20, SEEK_SET))
+ return SB_VERSION_UNK;
+ if(fread(sig, 4, 1, f) != 1)
+ return SB_VERSION_UNK;
+ if(memcmp(sig, "STMP", 4) != 0)
+ return SB_VERSION_UNK;
+ // check header size (v1)
+ uint32_t hdr_size;
+ if(fseek(f, 8, SEEK_SET))
+ return SB_VERSION_UNK;
+ if(fread(&hdr_size, 4, 1, f) != 1)
+ return SB_VERSION_UNK;
+ if(hdr_size == 0x34)
+ return SB_VERSION_1;
+ // check header size (v2)
+ if(fseek(f, 32, SEEK_SET))
+ return SB_VERSION_UNK;
+ if(fread(&hdr_size, 4, 1, f) != 1)
+ return SB_VERSION_UNK;
+ if(hdr_size == 0xc)
+ return SB_VERSION_2;
+ return SB_VERSION_UNK;
+}
+
int main(int argc, char **argv)
{
bool raw_mode = false;
const char *loopback = NULL;
-
+ bool force_sb1 = false;
+ bool force_sb2 = false;
+
+ /* decrypt the xor key which is xor'ed */
+ for(int i = 0; i < 2; i++)
+ for(int j = 0; j < 16; j++)
+ g_default_xor_key.u.xor_key[i].k[j] ^= 0xaa55aa55;
+
while(1)
{
static struct option long_options[] =
@@ -205,11 +278,13 @@ int main(int argc, char **argv)
{"add-key", required_argument, 0, 'a'},
{"no-color", no_argument, 0, 'n'},
{"loopback", required_argument, 0, 'l'},
- {"force", no_argument, 0, 'f' },
+ {"force", no_argument, 0, 'f'},
+ {"v1", no_argument, 0, '1'},
+ {"v2", no_argument, 0, '2'},
{0, 0, 0, 0}
};
- int c = getopt_long(argc, argv, "?do:k:zra:nl:f", long_options, NULL);
+ int c = getopt_long(argc, argv, "?do:k:zra:nl:f12x", long_options, NULL);
if(c == -1)
break;
switch(c)
@@ -243,10 +318,11 @@ int main(int argc, char **argv)
break;
}
case 'z':
- {
add_keys(&g_zero_key, 1);
break;
- }
+ case 'x':
+ add_keys(&g_default_xor_key, 1);
+ break;
case 'r':
raw_mode = true;
break;
@@ -261,11 +337,20 @@ int main(int argc, char **argv)
add_keys(&key, 1);
break;
}
+ case '1':
+ force_sb1 = true;
+ break;
+ case '2':
+ force_sb2 = true;
+ break;
default:
abort();
}
}
+ if(force_sb1 && force_sb2)
+ bug("You cannot force both version 1 and 2\n");
+
if(argc - optind != 1)
{
usage();
@@ -274,34 +359,70 @@ int main(int argc, char **argv)
const char *sb_filename = argv[optind];
- enum sb_error_t err;
- struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf, &err);
- if(file == NULL)
+ enum sb_version_guess_t ver = guess_sb_version(sb_filename);
+
+ if(force_sb2 || ver == SB_VERSION_2)
{
+ enum sb_error_t err;
+ struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf, &err);
+ if(file == NULL)
+ {
+ color(OFF);
+ printf("SB read failed: %d\n", err);
+ return 1;
+ }
+
color(OFF);
- printf("SB read failed: %d\n", err);
- return 1;
+ if(g_out_prefix)
+ extract_sb_file(file);
+ if(g_debug)
+ {
+ color(GREY);
+ printf("[Debug output]\n");
+ sb_dump(file, NULL, sb_printf);
+ }
+ if(loopback)
+ {
+ /* sb_read_file will fill real key and IV but we don't want to override
+ * them when looping back otherwise the output will be inconsistent and
+ * garbage */
+ file->override_real_key = false;
+ file->override_crypto_iv = false;
+ sb_write_file(file, loopback);
+ }
+ sb_free(file);
}
-
- color(OFF);
- if(g_out_prefix)
- extract_sb_file(file);
- if(g_debug)
+ else if(force_sb1 || ver == SB_VERSION_1)
{
- color(GREY);
- printf("[Debug output]\n");
- sb_dump(file, NULL, sb_printf);
+ enum sb1_error_t err;
+ struct sb1_file_t *file = sb1_read_file(sb_filename, NULL, sb_printf, &err);
+ if(file == NULL)
+ {
+ color(OFF);
+ printf("SB read failed: %d\n", err);
+ return 1;
+ }
+
+ color(OFF);
+ if(g_out_prefix)
+ extract_sb1_file(file);
+ if(g_debug)
+ {
+ color(GREY);
+ printf("[Debug output]\n");
+ sb1_dump(file, NULL, sb_printf);
+ }
+ if(loopback)
+ sb1_write_file(file, loopback);
+
+ sb1_free(file);
}
- if(loopback)
+ else
{
- /* sb_read_file will fill real key and IV but we don't want to override
- * them when looping back otherwise the output will be inconsistent and
- * garbage */
- file->override_real_key = false;
- file->override_crypto_iv = false;
- sb_write_file(file, loopback);
+ color(OFF);
+ printf("Cannot guess file type, are you sure it's a valid image ?\n");
+ return 1;
}
- sb_free(file);
clear_keys();
return 0;