summaryrefslogtreecommitdiff
path: root/utils/imxtools
diff options
context:
space:
mode:
Diffstat (limited to 'utils/imxtools')
-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 7a09d86..7d00e4b 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 d4afc6c..d73547d 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 452db6a..599ebf4 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 0000000..19f53b0
--- /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 0000000..f0a7a4e
--- /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 0170ea1..0445c4a 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;