diff --git a/utils/imx_hid_recovery/Makefile b/utils/imx_hid_recovery/Makefile deleted file mode 100644 index 24d0b8e3d3..0000000000 --- a/utils/imx_hid_recovery/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -CC=gcc -LD=gcc - -all: imx_hid_recovery - -imx_hid_recovery.o: imx_hid_recovery.c - $(CC) -c -Wall -O2 -std=c99 `pkg-config --cflags libusb-1.0` -o $@ $< - -imx_hid_recovery: imx_hid_recovery.o - $(LD) -o $@ $< `pkg-config --libs libusb-1.0` - -clean: - rm -rf imx_hid_recovery.o - - diff --git a/utils/sbtools/Makefile b/utils/imxtools/Makefile similarity index 79% rename from utils/sbtools/Makefile rename to utils/imxtools/Makefile index 69e63c9ac2..7a09d86d24 100644 --- a/utils/sbtools/Makefile +++ b/utils/imxtools/Makefile @@ -3,8 +3,9 @@ CC=gcc LD=gcc CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES) LDFLAGS=`pkg-config --libs libusb-1.0` +BINS=elftosb sbtoelf sbloader -all: elftosb sbtoelf +all: $(BINS) %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< @@ -15,8 +16,11 @@ sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o elf.o misc.o sb.o elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o $(LD) -o $@ $^ $(LDFLAGS) +sbloader: sbloader.o + $(LD) -o $@ $^ $(LDFLAGS) + clean: rm -fr *.o veryclean: - rm -rf sbtoelf elftosb + rm -rf $(BINS) diff --git a/utils/sbtools/README b/utils/imxtools/README similarity index 100% rename from utils/sbtools/README rename to utils/imxtools/README diff --git a/utils/sbtools/aes128.c b/utils/imxtools/aes128.c similarity index 100% rename from utils/sbtools/aes128.c rename to utils/imxtools/aes128.c diff --git a/utils/sbtools/crc.c b/utils/imxtools/crc.c similarity index 100% rename from utils/sbtools/crc.c rename to utils/imxtools/crc.c diff --git a/utils/sbtools/crypto.c b/utils/imxtools/crypto.c similarity index 100% rename from utils/sbtools/crypto.c rename to utils/imxtools/crypto.c diff --git a/utils/sbtools/crypto.h b/utils/imxtools/crypto.h similarity index 99% rename from utils/sbtools/crypto.h rename to utils/imxtools/crypto.h index 51f44406db..452db6a28d 100644 --- a/utils/sbtools/crypto.h +++ b/utils/imxtools/crypto.h @@ -63,6 +63,7 @@ void crypto_setup(enum crypto_method_t method, void *param); #define CRYPTO_ERROR_DEVREJECT -5 /* device rejected cypto operation */ #define CRYPTO_ERROR_DEVSILENT -6 /* device did not notify completion */ #define CRYPTO_ERROR_DEVERR -7 /* device did something wrong (like return too small buffer) */ +#define CRYPTO_NUM_ERRORS 8 /* return 0 on success, <0 on error */ int crypto_apply( byte *in_data, /* Input data */ diff --git a/utils/sbtools/dbparser.c b/utils/imxtools/dbparser.c similarity index 86% rename from utils/sbtools/dbparser.c rename to utils/imxtools/dbparser.c index 3cd0652d49..b2027e5ad7 100644 --- a/utils/sbtools/dbparser.c +++ b/utils/imxtools/dbparser.c @@ -19,6 +19,7 @@ * ****************************************************************************/ +#define _POSIX_C_SOURCE 200809L /* for strdup */ #include #include #include @@ -48,6 +49,7 @@ enum lexem_type_t struct lexem_t { enum lexem_type_t type; + /* if str is not NULL, it must be a malloc'd pointer */ char *str; uint32_t num; int line; @@ -390,8 +392,15 @@ struct lex_ctx_t struct lexem_t lexem; }; -static inline void next(struct lex_ctx_t *ctx) +/* When lexems hold strings (like identifier), it might be useful to steal + * the pointer and don't clean the lexem but in other case, one don't want + * to keep the pointer to the string and just want to release the memory. + * Thus clean_lexem should be true except when one keeps a pointer */ +static inline void next(struct lex_ctx_t *ctx, bool clean_lexem) { + if(clean_lexem) + free(ctx->lexem.str); + memset(&ctx->lexem, 0, sizeof(struct lexem_t)); next_lexem(&ctx->ctx, &ctx->lexem); } @@ -411,7 +420,7 @@ static uint32_t parse_term_expr(struct lex_ctx_t *ctx, struct cmd_option_t *cons } else parse_error(ctx->lexem, "Number or constant identifier expected\n"); - next(ctx); + next(ctx, true); return ret; } @@ -420,7 +429,7 @@ static uint32_t parse_shift_expr(struct lex_ctx_t *ctx, struct cmd_option_t *con uint32_t v = parse_term_expr(ctx, const_list); while(ctx->lexem.type == LEX_LSHIFT) { - next(ctx); + next(ctx, true); v <<= parse_term_expr(ctx, const_list); } return v; @@ -431,7 +440,7 @@ static uint32_t parse_or_expr(struct lex_ctx_t *ctx, struct cmd_option_t *const_ uint32_t v = parse_shift_expr(ctx, const_list); while(ctx->lexem.type == LEX_OR) { - next(ctx); + next(ctx, true); v |= parse_shift_expr(ctx, const_list); } return v; @@ -470,7 +479,7 @@ struct cmd_file_t *db_parse_file(const char *file) { struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); memset(opt, 0, sizeof(struct cmd_option_t)); - opt->name = init_const_name[i]; + opt->name = strdup(init_const_name[i]); opt->is_string = false; opt->val = init_const_value[i]; opt->next = cmd_file->constant_list; @@ -483,14 +492,14 @@ struct cmd_file_t *db_parse_file(const char *file) lctx.ctx.begin = buf; lctx.ctx.ptr = buf; lctx.ctx.end = buf + size; - #define next() next(&lctx) + #define next(clean_lexem) next(&lctx, clean_lexem) #define lexem lctx.lexem /* init lexer */ - next(); + next(false); /* don't clean init lexem because it doesn't exist */ /* constants ? */ if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "constants")) { - next(); + next(true); if(lexem.type != LEX_LBRACE) parse_error(lexem, "'{' expected after 'constants'\n"); @@ -498,16 +507,16 @@ struct cmd_file_t *db_parse_file(const char *file) { struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); memset(opt, 0, sizeof(struct cmd_option_t)); - next(); + next(true); if(lexem.type == LEX_RBRACE) break; if(lexem.type != LEX_IDENTIFIER) parse_error(lexem, "Identifier expected in constants\n"); opt->name = lexem.str; - next(); + next(false); /* lexem string is kept as option name */ if(lexem.type != LEX_EQUAL) parse_error(lexem, "'=' expected after identifier\n"); - next(); + next(true); opt->is_string = false; opt->val = parse_intexpr(&lctx, cmd_file->constant_list); opt->next = cmd_file->constant_list; @@ -515,34 +524,34 @@ struct cmd_file_t *db_parse_file(const char *file) if(lexem.type != LEX_SEMICOLON) parse_error(lexem, "';' expected after string\n"); } - next(); + next(true); } /* options ? */ if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "options")) { - next(); + next(true); if(lexem.type != LEX_LBRACE) parse_error(lexem, "'{' expected after 'options'\n"); while(true) { - struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); - memset(opt, 0, sizeof(struct cmd_option_t)); - next(); + next(true); if(lexem.type == LEX_RBRACE) break; + struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); + memset(opt, 0, sizeof(struct cmd_option_t)); if(lexem.type != LEX_IDENTIFIER) parse_error(lexem, "Identifier expected in options\n"); opt->name = lexem.str; - next(); + next(false); /* lexem string is kept as option name */ if(lexem.type != LEX_EQUAL) parse_error(lexem, "'=' expected after identifier\n"); - next(); + next(true); if(lexem.type == LEX_STRING) { opt->is_string = true; opt->str = lexem.str; - next(); + next(false); /* lexem string is kept as option name */ } else { @@ -554,18 +563,18 @@ struct cmd_file_t *db_parse_file(const char *file) if(lexem.type != LEX_SEMICOLON) parse_error(lexem, "';' expected after string\n"); } - next(); + next(true); } /* sources */ if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "sources")) parse_error(lexem, "'sources' expected\n"); - next(); + next(true); if(lexem.type != LEX_LBRACE) parse_error(lexem, "'{' expected after 'sources'\n"); while(true) { - next(); + next(true); if(lexem.type == LEX_RBRACE) break; struct cmd_source_t *src = xmalloc(sizeof(struct cmd_source_t)); @@ -573,28 +582,28 @@ struct cmd_file_t *db_parse_file(const char *file) if(lexem.type != LEX_IDENTIFIER) parse_error(lexem, "identifier expected in sources\n"); src->identifier = lexem.str; - next(); + next(false); /* lexem string is kept as source name */ if(lexem.type != LEX_EQUAL) parse_error(lexem, "'=' expected after identifier\n"); - next(); + next(true); if(lexem.type == LEX_STRING) { src->is_extern = false; src->filename = lexem.str; - next(); + next(false); /* lexem string is kept as file name */ } else if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "extern")) { src->is_extern = true; - src->filename = ""; - next(); + src->filename = strdup(""); /* duplicate because it will be free'd */ + next(true); if(lexem.type != LEX_LPAREN) parse_error(lexem, "'(' expected after 'extern'\n"); - next(); + next(true); src->extern_nr = parse_intexpr(&lctx, cmd_file->constant_list); if(lexem.type != LEX_RPAREN) parse_error(lexem, "')' expected\n"); - next(); + next(true); } else parse_error(lexem, "String or 'extern' expected after '='\n"); @@ -612,18 +621,18 @@ struct cmd_file_t *db_parse_file(const char *file) struct cmd_section_t *end_sec = NULL; while(true) { + next(true); + if(lexem.type == LEX_EOF) + break; struct cmd_section_t *sec = xmalloc(sizeof(struct cmd_section_t)); struct cmd_inst_t *end_list = NULL; memset(sec, 0, sizeof(struct cmd_section_t)); - next(); - if(lexem.type == LEX_EOF) - break; if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "section") != 0) parse_error(lexem, "'section' expected\n"); - next(); + next(true); if(lexem.type != LEX_LPAREN) parse_error(lexem, "'(' expected after 'section'\n"); - next(); + next(true); /* can be any number */ sec->identifier = parse_intexpr(&lctx, cmd_file->constant_list); /* options ? */ @@ -631,21 +640,21 @@ struct cmd_file_t *db_parse_file(const char *file) { do { - next(); + next(true); struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); memset(opt, 0, sizeof(struct cmd_option_t)); if(lexem.type != LEX_IDENTIFIER) parse_error(lexem, "Identifier expected for section option\n"); opt->name = lexem.str; - next(); + next(false); /* lexem string is kept as option name */ if(lexem.type != LEX_EQUAL) parse_error(lexem, "'=' expected after option identifier\n"); - next(); + next(true); if(lexem.type == LEX_STRING) { opt->is_string = true; opt->str = lexem.str; - next(); + next(false); /* lexem string is kept as option string */ } else { @@ -658,18 +667,18 @@ struct cmd_file_t *db_parse_file(const char *file) } if(lexem.type != LEX_RPAREN) parse_error(lexem, "')' expected after section identifier\n"); - next(); + next(true); if(lexem.type == LEX_LBRACE) { sec->is_data = false; /* commands */ while(true) { - struct cmd_inst_t *inst = xmalloc(sizeof(struct cmd_inst_t)); - memset(inst, 0, sizeof(struct cmd_inst_t)); - next(); + next(true); if(lexem.type == LEX_RBRACE) break; + struct cmd_inst_t *inst = xmalloc(sizeof(struct cmd_inst_t)); + memset(inst, 0, sizeof(struct cmd_inst_t)); if(lexem.type != LEX_IDENTIFIER) parse_error(lexem, "Instruction expected in section\n"); if(strcmp(lexem.str, "load") == 0) @@ -682,7 +691,7 @@ struct cmd_file_t *db_parse_file(const char *file) inst->type = CMD_MODE; else parse_error(lexem, "Instruction expected in section\n"); - next(); + next(true); if(inst->type == CMD_LOAD) { @@ -691,12 +700,12 @@ struct cmd_file_t *db_parse_file(const char *file) inst->identifier = lexem.str; if(db_find_source_by_id(cmd_file, inst->identifier) == NULL) parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier); - next(); + next(false); /* lexem string kept as identifier */ if(lexem.type == LEX_RANGLE) { // load at inst->type = CMD_LOAD_AT; - next(); + next(true); inst->addr = parse_intexpr(&lctx, cmd_file->constant_list); } if(lexem.type != LEX_SEMICOLON) @@ -709,7 +718,7 @@ struct cmd_file_t *db_parse_file(const char *file) inst->identifier = lexem.str; if(db_find_source_by_id(cmd_file, inst->identifier) == NULL) parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier); - next(); + next(false); /* lexem string kept as identifier */ } else { @@ -719,11 +728,11 @@ struct cmd_file_t *db_parse_file(const char *file) if(lexem.type == LEX_LPAREN) { - next(); + next(true); inst->argument = parse_intexpr(&lctx, cmd_file->constant_list); if(lexem.type != LEX_RPAREN) parse_error(lexem, "Expected closing brace\n"); - next(); + next(true); } if(lexem.type != LEX_SEMICOLON) parse_error(lexem, "';' expected after command\n"); @@ -751,11 +760,11 @@ struct cmd_file_t *db_parse_file(const char *file) else if(lexem.type == LEX_LE) { sec->is_data = true; - next(); + next(true); if(lexem.type != LEX_IDENTIFIER) parse_error(lexem, "Identifier expected after '<='\n"); sec->source_id = lexem.str; - next(); + next(false); /* lexem string is kept as source id */ if(lexem.type != LEX_SEMICOLON) parse_error(lexem, "';' expected after identifier\n"); } @@ -776,6 +785,7 @@ struct cmd_file_t *db_parse_file(const char *file) #undef lexem #undef next + free(buf); return cmd_file; } @@ -783,3 +793,57 @@ void db_generate_default_sb_version(struct sb_version_t *ver) { ver->major = ver->minor = ver->revision = 0x999; } + +void db_free_option_list(struct cmd_option_t *opt_list) +{ + while(opt_list) + { + struct cmd_option_t *next = opt_list->next; + fflush(stdout); + free(opt_list->name); + free(opt_list->str); + free(opt_list); + opt_list = next; + } +} + +void db_free(struct cmd_file_t *file) +{ + db_free_option_list(file->opt_list); + db_free_option_list(file->constant_list); + struct cmd_source_t *src = file->source_list; + while(src) + { + struct cmd_source_t *next = src->next; + free(src->identifier); + fflush(stdout); + free(src->filename); + if(src->loaded) + { + if(src->type == CMD_SRC_BIN) + free(src->bin.data); + if(src->type == CMD_SRC_ELF) + elf_release(&src->elf); + } + free(src); + src = next; + } + struct cmd_section_t *sec = file->section_list; + while(sec) + { + struct cmd_section_t *next = sec->next; + db_free_option_list(sec->opt_list); + free(sec->source_id); + struct cmd_inst_t *inst = sec->inst_list; + while(inst) + { + struct cmd_inst_t *next = inst->next; + free(inst->identifier); + free(inst); + inst = next; + } + free(sec); + sec = next; + } + free(file); +} diff --git a/utils/sbtools/dbparser.h b/utils/imxtools/dbparser.h similarity index 94% rename from utils/sbtools/dbparser.h rename to utils/imxtools/dbparser.h index cfb1a692fa..4a36861583 100644 --- a/utils/sbtools/dbparser.h +++ b/utils/imxtools/dbparser.h @@ -102,7 +102,7 @@ struct cmd_section_t struct cmd_file_t { struct cmd_option_t *opt_list; - struct cmd_option_t *constant_list; /* constant all always integers */ + struct cmd_option_t *constant_list; /* constant are always integers */ struct cmd_source_t *source_list; struct cmd_section_t *section_list; }; @@ -112,5 +112,7 @@ struct cmd_option_t *db_find_option_by_id(struct cmd_option_t *opt, const char * bool db_parse_sb_version(struct sb_version_t *ver, char *str); void db_generate_default_sb_version(struct sb_version_t *ver); struct cmd_file_t *db_parse_file(const char *file); +void db_free_option_list(struct cmd_option_t *opt_list); +void db_free(struct cmd_file_t *file); #endif /* __DBPARSER__ */ diff --git a/utils/sbtools/elf.c b/utils/imxtools/elf.c similarity index 97% rename from utils/sbtools/elf.c rename to utils/imxtools/elf.c index 91b5d74848..481ab98dd6 100644 --- a/utils/sbtools/elf.c +++ b/utils/imxtools/elf.c @@ -153,10 +153,7 @@ typedef struct void elf_init(struct elf_params_t *params) { - params->has_start_addr = false; - params->start_addr = 0; - params->first_section = NULL; - params->last_section = NULL; + memset(params, 0, sizeof(struct elf_params_t)); } extern void *xmalloc(size_t s); @@ -463,6 +460,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, if(!read(user, shdr.sh_offset, data, shdr.sh_size)) error_printf("error read self section data\n"); elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data); + free(data); if(strtab) printf(user, false, "create load segment for %s\n", &strtab[shdr.sh_name]); @@ -480,6 +478,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, } } + free(strtab); /* run through segments */ for(int i = 1; i < ehdr.e_phnum; i++) { @@ -557,16 +556,20 @@ int elf_get_nr_sections(struct elf_params_t *params) void elf_release(struct elf_params_t *params) { - struct elf_section_t *sec, *next_sec; - sec = params->first_section; + struct elf_section_t *sec = params->first_section; while(sec) { - next_sec = sec->next; + struct elf_section_t *next_sec = sec->next; if(sec->type == EST_LOAD) free(sec->section); free(sec); sec = next_sec; } - params->first_section = NULL; - params->last_section = NULL; + struct elf_segment_t *seg = params->first_segment; + while(seg) + { + struct elf_segment_t *next_seg = seg->next; + free(seg); + seg = next_seg; + } } diff --git a/utils/sbtools/elf.h b/utils/imxtools/elf.h similarity index 100% rename from utils/sbtools/elf.h rename to utils/imxtools/elf.h diff --git a/utils/sbtools/elftosb.c b/utils/imxtools/elftosb.c similarity index 95% rename from utils/sbtools/elftosb.c rename to utils/imxtools/elftosb.c index b8d68b82e7..2f8700551f 100644 --- a/utils/sbtools/elftosb.c +++ b/utils/imxtools/elftosb.c @@ -20,6 +20,7 @@ ****************************************************************************/ #define _ISOC99_SOURCE +#define _POSIX_C_SOURCE 200809L /* for strdup */ #include #include #include @@ -77,7 +78,9 @@ static void resolve_extern(struct cmd_source_t *src) src->is_extern = false; if(src->extern_nr < 0 || src->extern_nr >= g_extern_count) bug("There aren't enough file on command file to resolve extern(%d)\n", src->extern_nr); - src->filename = g_extern[src->extern_nr]; + /* first free the old src->filename content */ + free(src->filename); + src->filename = strdup(g_extern[src->extern_nr]); } static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id) @@ -206,7 +209,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) sec->insts[0].inst = SB_INST_DATA; sec->insts[0].size = bin->size; - sec->insts[0].data = bin->data; + sec->insts[0].data = memdup(bin->data, bin->size); } else { @@ -266,7 +269,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) sec->insts[idx].inst = SB_INST_LOAD; sec->insts[idx].addr = esec->addr; sec->insts[idx].size = esec->size; - sec->insts[idx++].data = esec->section; + sec->insts[idx++].data = memdup(esec->section, esec->size); } else if(esec->type == EST_FILL) { @@ -296,7 +299,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) struct bin_param_t *bin = &db_find_source_by_id(cmd_file, cinst->identifier)->bin; sec->insts[idx].inst = SB_INST_LOAD; sec->insts[idx].addr = cinst->addr; - sec->insts[idx].data = bin->data; + sec->insts[idx].data = memdup(bin->data, bin->size); sec->insts[idx++].size = bin->size; } else if(cinst->type == CMD_MODE) @@ -431,11 +434,18 @@ int main(int argc, char **argv) struct cmd_file_t *cmd_file = db_parse_file(cmd_filename); struct sb_file_t *sb_file = apply_cmd_file(cmd_file); + db_free(cmd_file); if(real_key.method == CRYPTO_KEY) - sb_file->real_key = &real_key.u.key; + { + sb_file->override_real_key = true; + memcpy(sb_file->real_key, real_key.u.key, 16); + } if(crypto_iv.method == CRYPTO_KEY) - sb_file->crypto_iv = &crypto_iv.u.key; + { + sb_file->override_crypto_iv = true; + memcpy(sb_file->crypto_iv, crypto_iv.u.key, 16); + } /* fill with default parameters since there is no command file support for them */ sb_file->drive_tag = 0; @@ -444,6 +454,8 @@ int main(int argc, char **argv) sb_file->minor_version = 1; sb_write_file(sb_file, output_filename); + sb_free(sb_file); + clear_keys(); return 0; } diff --git a/utils/sbtools/fuze+_key_file.txt b/utils/imxtools/fuze+_key_file.txt similarity index 100% rename from utils/sbtools/fuze+_key_file.txt rename to utils/imxtools/fuze+_key_file.txt diff --git a/utils/sbtools/misc.c b/utils/imxtools/misc.c similarity index 97% rename from utils/sbtools/misc.c rename to utils/imxtools/misc.c index 4eeda4ef33..8d7cea89d7 100644 --- a/utils/sbtools/misc.c +++ b/utils/imxtools/misc.c @@ -29,6 +29,14 @@ bool g_debug = false; /** * Misc */ + +void *memdup(void *p, size_t len) +{ + void *cpy = xmalloc(len); + memcpy(cpy, p, len); + return cpy; +} + void generate_random_data(void *buf, size_t sz) { FILE *rand_fd = fopen("/dev/urandom", "rb"); @@ -144,6 +152,12 @@ void add_keys(key_array_t ka, int kac) g_nr_keys += kac; } +void clear_keys() +{ + free(g_key_array); + g_nr_keys = 0; +} + void add_keys_from_file(const char *key_file) { int size; diff --git a/utils/sbtools/misc.h b/utils/imxtools/misc.h similarity index 97% rename from utils/sbtools/misc.h rename to utils/imxtools/misc.h index 9f14497680..b0b7dfeba6 100644 --- a/utils/sbtools/misc.h +++ b/utils/imxtools/misc.h @@ -38,6 +38,7 @@ typedef struct crypto_key_t *key_array_t; int g_nr_keys; key_array_t g_key_array; +void *memdup(void *p, size_t len); void *augment_array(void *arr, size_t elem_sz, size_t cnt, void *aug, size_t aug_cnt); void generate_random_data(void *buf, size_t sz); void *xmalloc(size_t s); @@ -47,6 +48,7 @@ void add_keys(key_array_t ka, int kac); bool parse_key(char **str, struct crypto_key_t *key); void add_keys_from_file(const char *key_file); void print_key(struct crypto_key_t *key, bool newline); +void clear_keys(); typedef char color_t[]; diff --git a/utils/sbtools/sb.c b/utils/imxtools/sb.c similarity index 85% rename from utils/sbtools/sb.c rename to utils/imxtools/sb.c index d620c00f42..44db56b7d1 100644 --- a/utils/sbtools/sb.c +++ b/utils/imxtools/sb.c @@ -138,7 +138,7 @@ static void compute_sb_offsets(struct sb_file_t *sb) if(sb->sections[i].is_data) { nr_aug_insts = 1; - aug_insts = malloc(sizeof(struct sb_inst_t)); + aug_insts = xmalloc(sizeof(struct sb_inst_t)); memset(aug_insts, 0, sizeof(struct sb_inst_t)); aug_insts[0].inst = SB_INST_DATA; aug_insts[0].size = missing_sz * BLOCK_SIZE; @@ -150,7 +150,7 @@ static void compute_sb_offsets(struct sb_file_t *sb) else { nr_aug_insts = missing_sz; - aug_insts = malloc(sizeof(struct sb_inst_t) * nr_aug_insts); + aug_insts = xmalloc(sizeof(struct sb_inst_t) * nr_aug_insts); memset(aug_insts, 0, sizeof(struct sb_inst_t) * nr_aug_insts); for(int j = 0; j < nr_aug_insts; j++) { @@ -163,6 +163,7 @@ static void compute_sb_offsets(struct sb_file_t *sb) sb->sections[i].insts = augment_array(sb->sections[i].insts, sizeof(struct sb_inst_t), sb->sections[i].nr_insts, aug_insts, nr_aug_insts); sb->sections[i].nr_insts += nr_aug_insts; + free(aug_insts); /* augment image and section size */ sb->image_size += missing_sz; @@ -299,12 +300,8 @@ void produce_sb_instruction(struct sb_inst_t *inst, cmd->hdr.checksum = instruction_checksum(&cmd->hdr); } -void sb_write_file(struct sb_file_t *sb, const char *filename) +enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename) { - FILE *fd = fopen(filename, "wb"); - if(fd == NULL) - bugp("cannot open output file"); - struct crypto_key_t real_key; real_key.method = CRYPTO_KEY; byte crypto_iv[16]; @@ -324,8 +321,13 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) /* produce and write header */ struct sb_header_t sb_hdr; produce_sb_header(sb, &sb_hdr); + /* allocate image */ + byte *buf = xmalloc(sb_hdr.image_size * BLOCK_SIZE); + byte *buf_p = buf; + #define write(p, sz) do { memcpy(buf_p, p, sz); buf_p += sz; } while(0) + sha_1_update(&file_sha1, (byte *)&sb_hdr, sizeof(sb_hdr)); - fwrite(&sb_hdr, 1, sizeof(sb_hdr), fd); + write(&sb_hdr, sizeof(sb_hdr)); memcpy(crypto_iv, &sb_hdr, 16); @@ -340,7 +342,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) struct sb_section_header_t sb_sec_hdr; produce_sb_section_header(&sb->sections[i], &sb_sec_hdr); sha_1_update(&file_sha1, (byte *)&sb_sec_hdr, sizeof(sb_sec_hdr)); - fwrite(&sb_sec_hdr, 1, sizeof(sb_sec_hdr), fd); + write(&sb_sec_hdr, sizeof(sb_sec_hdr)); /* update CBC-MACs */ for(int j = 0; j < g_nr_keys; j++) crypto_cbc((byte *)&sb_sec_hdr, NULL, sizeof(sb_sec_hdr) / BLOCK_SIZE, @@ -354,16 +356,18 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) crypto_cbc(real_key.u.key, entry.key, 1, &g_key_array[i], crypto_iv, NULL, 1); - fwrite(&entry, 1, sizeof(entry), fd); + write(&entry, sizeof(entry)); sha_1_update(&file_sha1, (byte *)&entry, sizeof(entry)); } + free(cbc_macs); + /* HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK */ /* Image crafting, don't use it unless you understand what you do */ - if(sb->real_key != NULL) - memcpy(real_key.u.key, *sb->real_key, 16); - if(sb->crypto_iv != NULL) - memcpy(crypto_iv, *sb->crypto_iv, 16); + if(sb->override_real_key) + memcpy(real_key.u.key, sb->real_key, 16); + if(sb->override_crypto_iv) + memcpy(crypto_iv, sb->crypto_iv, 16); /* KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH */ if(g_debug) { @@ -386,7 +390,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) crypto_cbc((byte *)&tag_cmd, (byte *)&tag_cmd, sizeof(tag_cmd) / BLOCK_SIZE, &real_key, crypto_iv, NULL, 1); sha_1_update(&file_sha1, (byte *)&tag_cmd, sizeof(tag_cmd)); - fwrite(&tag_cmd, 1, sizeof(tag_cmd), fd); + write(&tag_cmd, sizeof(tag_cmd)); /* produce other commands */ byte cur_cbc_mac[16]; memcpy(cur_cbc_mac, crypto_iv, 16); @@ -402,7 +406,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) crypto_cbc((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE, &real_key, cur_cbc_mac, &cur_cbc_mac, 1); sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd)); - fwrite(&cmd, 1, sizeof(cmd), fd); + write(&cmd, sizeof(cmd)); } /* data */ if(inst->inst == SB_INST_LOAD || inst->inst == SB_INST_DATA) @@ -415,7 +419,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) crypto_cbc(data, data, sz / BLOCK_SIZE, &real_key, cur_cbc_mac, &cur_cbc_mac, 1); sha_1_update(&file_sha1, data, sz); - fwrite(data, 1, sz, fd); + write(data, sz); free(data); } } @@ -427,22 +431,35 @@ void sb_write_file(struct sb_file_t *sb, const char *filename) generate_random_data(final_sig + 20, 12); if(g_nr_keys > 0) crypto_cbc(final_sig, final_sig, 2, &real_key, crypto_iv, NULL, 1); - fwrite(final_sig, 1, 32, fd); - - fclose(fd); -} + write(final_sig, 32); -static void *memdup(void *p, size_t len) -{ - void *cpy = xmalloc(len); - memcpy(cpy, p, len); - return cpy; + if(buf_p - buf != sb_hdr.image_size * BLOCK_SIZE) + bug("SB image buffer was not entirely filled !"); + + FILE *fd = fopen(filename, "wb"); + if(fd == NULL) + return SB_OPEN_ERROR; + if(fwrite(buf, sb_hdr.image_size * BLOCK_SIZE, 1, fd) != 1) + { + free(buf); + return SB_WRITE_ERROR; + } + fclose(fd); + free(buf); + + return SB_SUCCESS; } static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, - int size, const char *indent, void *u, sb_color_printf cprintf) + int size, const char *indent, void *u, sb_color_printf cprintf, enum sb_error_t *err) { #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__) + #define fatal(e, ...) \ + do { if(err) *err = e; \ + cprintf(u, true, GREY, __VA_ARGS__); \ + sb_free_section(*sec); \ + free(sec); \ + return NULL; } while(0) struct sb_section_t *sec = xmalloc(sizeof(struct sb_section_t)); memset(sec, 0, sizeof(struct sb_section_t)); @@ -474,7 +491,7 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, printf(OFF, "%s", indent); uint8_t checksum = instruction_checksum(hdr); if(checksum != hdr->checksum) - printf(GREY, "[Bad checksum]"); + fatal(SB_CHECKSUM_ERROR, "Bad instruction checksum"); if(hdr->flags != 0) { printf(GREY, "["); @@ -501,7 +518,10 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, if(load->crc == computed_crc) printf(RED, " Ok\n"); else + { printf(RED, " Failed (crc=0x%08x)\n", computed_crc); + fatal(SB_CHECKSUM_ERROR, "Instruction data crc error\n"); + } pos += load->len + sizeof(struct sb_instruction_load_t); } @@ -559,7 +579,7 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, } else { - printf(RED, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos); + fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos); break; } @@ -569,6 +589,7 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf, return sec; #undef printf + #undef fatal } void sb_fill_section_name(char name[5], uint32_t identifier) @@ -595,25 +616,37 @@ static uint32_t guess_alignment(uint32_t off) } struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, - sb_color_printf cprintf) + sb_color_printf cprintf, enum sb_error_t *err) { + uint8_t *buf = NULL; + struct sb_file_t *sb_file = NULL; + #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__) - #define fatal(...) do { cprintf(u, true, GREY, __VA_ARGS__); return NULL; } while(0) + #define fatal(e, ...) \ + do { if(err) *err = e; \ + cprintf(u, true, GREY, __VA_ARGS__); \ + free(buf); \ + sb_free(sb_file); \ + return NULL; } while(0) #define print_hex(c, p, len, nl) \ do { printf(c, ""); print_hex(p, len, nl); } while(0) FILE *f = fopen(filename, "rb"); if(f == NULL) - fatal("Cannot open file for reading\n"); + fatal(SB_OPEN_ERROR, "Cannot open file for reading\n"); fseek(f, 0, SEEK_END); long filesize = ftell(f); fseek(f, 0, SEEK_SET); - uint8_t *buf = xmalloc(filesize); - fread(buf, 1, filesize, f); + buf = xmalloc(filesize); + if(fread(buf, filesize, 1, f) != 1) + { + fclose(f); + fatal(SB_READ_ERROR, "Cannot read file\n"); + } fclose(f); struct sha_1_params_t sha_1_params; - struct sb_file_t *sb_file = xmalloc(sizeof(struct sb_file_t)); + sb_file = xmalloc(sizeof(struct sb_file_t)); memset(sb_file, 0, sizeof(struct sb_file_t)); struct sb_header_t *sb_header = (struct sb_header_t *)buf; @@ -624,13 +657,13 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, sb_file->first_boot_sec_id = sb_header->first_boot_sec_id; if(memcmp(sb_header->signature, "STMP", 4) != 0) - fatal("Bad signature\n"); + fatal(SB_FORMAT_ERROR, "Bad signature\n"); if(sb_header->image_size * BLOCK_SIZE > filesize) - fatal("File too small mismatch"); + fatal(SB_FORMAT_ERROR, "File too small"); if(sb_header->header_size * BLOCK_SIZE != sizeof(struct sb_header_t)) - fatal("Bad header size"); + fatal(SB_FORMAT_ERROR, "Bad header size"); if(sb_header->sec_hdr_size * BLOCK_SIZE != sizeof(struct sb_section_header_t)) - fatal("Bad section header size"); + fatal(SB_FORMAT_ERROR, "Bad section header size"); if(filesize > sb_header->image_size * BLOCK_SIZE) { @@ -707,87 +740,107 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, /* encryption cbc-mac */ byte real_key[16]; bool valid_key = false; /* false until a matching key was found */ + if(sb_header->nr_keys > 0) { - if(sb_header->nr_keys > g_nr_keys) - { - fatal("SB file has %d keys but only %d were specified\n", - sb_header->nr_keys, g_nr_keys); - } - printf(BLUE, "Encryption data\n"); - for(int i = 0; i < sb_header->nr_keys; i++) + byte (*cbcmacs)[16] = xmalloc(16 * g_nr_keys); + printf(BLUE, "Encryption keys\n"); + for(int i = 0; i < g_nr_keys; i++) { printf(RED, " Key %d: ", i); printf(YELLOW, ""); print_key(&g_key_array[i], true); - printf(GREEN, " CBC-MAC of headers: "); + printf(GREEN, " CBC-MAC: "); + /* check it */ + byte zero[16]; + memset(zero, 0, 16); + int ret = crypto_cbc(buf, NULL, sb_header->header_size + sb_header->nr_sections, + &g_key_array[i], zero, &cbcmacs[i], 1); + if(ret != CRYPTO_ERROR_SUCCESS) + { + free(cbcmacs); + fatal(SB_FIRST_CRYPTO_ERROR + ret, "Crypto error: %d", ret); + } + print_hex(YELLOW, cbcmacs[i], 16, true); + } + printf(BLUE, "DEK\n"); + for(int i = 0; i < sb_header->nr_keys; i++) + { + printf(RED, " Entry %d\n", i); uint32_t ofs = sizeof(struct sb_header_t) + sizeof(struct sb_section_header_t) * sb_header->nr_sections + sizeof(struct sb_key_dictionary_entry_t) * i; struct sb_key_dictionary_entry_t *dict_entry = (struct sb_key_dictionary_entry_t *)&buf[ofs]; /* cbc mac */ + printf(GREEN, " Encrypted key: "); + print_hex(YELLOW, dict_entry->key, 16, true); + printf(GREEN, " CBC-MAC : "); print_hex(YELLOW, dict_entry->hdr_cbc_mac, 16, false); /* check it */ - byte computed_cbc_mac[16]; - byte zero[16]; - memset(zero, 0, 16); - crypto_cbc(buf, NULL, sb_header->header_size + sb_header->nr_sections, - &g_key_array[i], zero, &computed_cbc_mac, 1); - - bool ok = memcmp(dict_entry->hdr_cbc_mac, computed_cbc_mac, 16) == 0; - if(ok) + int idx = 0; + while(idx < g_nr_keys && memcmp(dict_entry->hdr_cbc_mac, cbcmacs[idx], 16) != 0) + idx++; + if(idx != g_nr_keys) { - valid_key = true; - printf(RED, " Ok\n"); + printf(RED, " Match\n"); + /* decrypt */ + byte decrypted_key[16]; + byte iv[16]; + memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */ + int ret = crypto_cbc(dict_entry->key, decrypted_key, 1, &g_key_array[idx], iv, NULL, 0); + if(ret != CRYPTO_ERROR_SUCCESS) + { + free(cbcmacs); + fatal(SB_FIRST_CRYPTO_ERROR + ret, "Crypto error: %d\n", ret); + } + printf(GREEN, " Decrypted key: "); + print_hex(YELLOW, decrypted_key, 16, false); + if(valid_key) + { + if(memcmp(real_key, decrypted_key, 16) == 0) + printf(RED, " Cross-Check Ok"); + else + printf(RED, " Cross-Check Failed"); + } + else + { + memcpy(real_key, decrypted_key, 16); + valid_key = true; + } + printf(OFF, "\n"); } else - printf(RED, " Failed\n"); - - printf(GREEN, " Encrypted key : "); - print_hex(YELLOW, dict_entry->key, 16, true); - /* decrypt */ - byte decrypted_key[16]; - byte iv[16]; - memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */ - crypto_cbc(dict_entry->key, decrypted_key, 1, &g_key_array[i], iv, NULL, 0); - printf(GREEN, " Decrypted key : "); - print_hex(YELLOW, decrypted_key, 16, false); - /* cross-check or copy */ - if(valid_key && ok) - memcpy(real_key, decrypted_key, 16); - else if(valid_key) - { - if(memcmp(real_key, decrypted_key, 16) == 0) - printf(RED, " Cross-Check Ok"); - else - printf(RED, " Cross-Check Failed"); - } - printf(OFF, "\n"); + printf(RED, " Don't Match\n"); } + + free(cbcmacs); + + if(!valid_key) + fatal(SB_NO_VALID_KEY, "No valid key found\n"); + + if(getenv("SB_REAL_KEY") != 0) + { + struct crypto_key_t k; + char *env = getenv("SB_REAL_KEY"); + if(!parse_key(&env, &k) || *env) + bug("Invalid SB_REAL_KEY\n"); + memcpy(real_key, k.u.key, 16); + } + + printf(RED, " Summary:\n"); + printf(GREEN, " Real key: "); + print_hex(YELLOW, real_key, 16, true); + printf(GREEN, " IV : "); + print_hex(YELLOW, buf, 16, true); + + sb_file->override_real_key = true; + memcpy(sb_file->real_key, real_key, 16); + sb_file->override_crypto_iv = true; + memcpy(sb_file->crypto_iv, buf, 16); } - if(getenv("SB_REAL_KEY") != 0) - { - struct crypto_key_t k; - char *env = getenv("SB_REAL_KEY"); - if(!parse_key(&env, &k) || *env) - bug("Invalid SB_REAL_KEY\n"); - memcpy(real_key, k.u.key, 16); - } - - printf(RED, " Summary:\n"); - printf(GREEN, " Real key: "); - print_hex(YELLOW, real_key, 16, true); - printf(GREEN, " IV : "); - print_hex(YELLOW, buf, 16, true); - - sb_file->real_key = xmalloc(16); - memcpy(*sb_file->real_key, real_key, 16); - sb_file->crypto_iv = xmalloc(16); - memcpy(*sb_file->crypto_iv, buf, 16); - /* sections */ if(!raw_mode) { @@ -831,7 +884,7 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, memcpy(sec, buf + pos, size); struct sb_section_t *s = read_section(data_sec, sec_hdr->identifier, - sec, size, " ", u, cprintf); + sec, size, " ", u, cprintf, err); if(s) { s->is_cleartext = !encrypted; @@ -839,6 +892,8 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, memcpy(&sb_file->sections[i], s, sizeof(struct sb_section_t)); free(s); } + else + fatal(*err, "Error reading section\n"); free(sec); } @@ -919,7 +974,7 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, memcpy(sec, buf + pos, size); struct sb_section_t *s = read_section(data_sec, tag->identifier, - sec, size, " ", u, cprintf); + sec, size, " ", u, cprintf, err); if(s) { s->is_cleartext = !encrypted; @@ -929,6 +984,8 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, s, 1); free(s); } + else + fatal(*err, "Error reading section\n"); free(sec); /* last one ? */ @@ -938,7 +995,7 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, } else { - printf(RED, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset); + fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset); break; } } @@ -970,7 +1027,10 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, if(memcmp(decrypted_block, computed_sha1, 20) == 0) printf(RED, " Ok\n"); else + { printf(RED, " Failed\n"); + fatal(SB_CHECKSUM_ERROR, "File SHA-1 error\n"); + } free(buf); return sb_file; @@ -979,6 +1039,27 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, #undef print_hex } +void sb_free_section(struct sb_section_t sec) +{ + for(int j = 0; j < sec.nr_insts; j++) + { + free(sec.insts[j].padding); + free(sec.insts[j].data); + } + free(sec.insts); +} + +void sb_free(struct sb_file_t *file) +{ + if(!file) return; + + for(int i = 0; i < file->nr_sections; i++) + sb_free_section(file->sections[i]); + + free(file->sections); + free(file); +} + void sb_dump(struct sb_file_t *file, void *u, sb_color_printf cprintf) { #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__) @@ -1007,17 +1088,17 @@ void sb_dump(struct sb_file_t *file, void *u, sb_color_printf cprintf) sb_fill_section_name(name, file->first_boot_sec_id); printf(TEXT, "%08x (%s)\n", file->first_boot_sec_id, name); - if(file->real_key) + if(file->override_real_key) { printf(TREE, "+-"); printf(HEADER, "Real key: "); - print_hex(TEXT, *file->real_key, 16, true); + print_hex(TEXT, file->real_key, 16, true); } - if(file->crypto_iv) + if(file->override_crypto_iv) { printf(TREE, "+-"); printf(HEADER, "IV : "); - print_hex(TEXT, *file->crypto_iv, 16, true); + print_hex(TEXT, file->crypto_iv, 16, true); } printf(TREE, "+-"); printf(HEADER, "Product Version: "); diff --git a/utils/sbtools/sb.h b/utils/imxtools/sb.h similarity index 90% rename from utils/sbtools/sb.h rename to utils/imxtools/sb.h index 39bb8ce59b..ced6481a80 100644 --- a/utils/sbtools/sb.h +++ b/utils/imxtools/sb.h @@ -191,9 +191,11 @@ struct sb_section_t struct sb_file_t { /* override real, otherwise it is randomly generated */ - uint8_t (*real_key)[16]; + bool override_real_key; + uint8_t real_key[16]; /* override crypto IV, use with caution ! Use NULL to generate it */ - uint8_t (*crypto_iv)[16]; + bool override_crypto_iv; + uint8_t crypto_iv[16]; int nr_sections; uint16_t drive_tag; @@ -207,13 +209,29 @@ struct sb_file_t uint32_t image_size; /* in blocks */ }; -void sb_write_file(struct sb_file_t *sb, const char *filename); +enum sb_error_t +{ + SB_SUCCESS = 0, + SB_ERROR = -1, + SB_OPEN_ERROR = -2, + SB_READ_ERROR = -3, + SB_WRITE_ERROR = -4, + SB_FORMAT_ERROR = -5, + SB_CHECKSUM_ERROR = -6, + SB_NO_VALID_KEY = -7, + SB_FIRST_CRYPTO_ERROR = -8, + SB_LAST_CRYPTO_ERROR = SB_FIRST_CRYPTO_ERROR - CRYPTO_NUM_ERRORS, +}; + +enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename); typedef void (*sb_color_printf)(void *u, bool err, color_t c, const char *f, ...); struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u, - sb_color_printf printf); + sb_color_printf printf, enum sb_error_t *err); void sb_fill_section_name(char name[5], uint32_t identifier); void sb_dump(struct sb_file_t *file, void *u, sb_color_printf printf); +void sb_free_section(struct sb_section_t file); +void sb_free(struct sb_file_t *file); #endif /* __SB_H__ */ diff --git a/utils/imx_hid_recovery/imx_hid_recovery.c b/utils/imxtools/sbloader.c similarity index 100% rename from utils/imx_hid_recovery/imx_hid_recovery.c rename to utils/imxtools/sbloader.c diff --git a/utils/sbtools/sbtoelf.c b/utils/imxtools/sbtoelf.c similarity index 96% rename from utils/sbtools/sbtoelf.c rename to utils/imxtools/sbtoelf.c index 179f91262f..fda70b1180 100644 --- a/utils/sbtools/sbtoelf.c +++ b/utils/imxtools/sbtoelf.c @@ -268,7 +268,15 @@ int main(int argc, char **argv) const char *sb_filename = argv[optind]; - struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf); + 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); if(g_out_prefix) extract_sb_file(file); @@ -283,12 +291,12 @@ int main(int argc, char **argv) /* 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 */ - free(file->real_key); - file->real_key = NULL; - free(file->crypto_iv); - file->crypto_iv = NULL; + file->override_real_key = false; + file->override_crypto_iv = false; sb_write_file(file, loopback); } + sb_free(file); + clear_keys(); return 0; } diff --git a/utils/sbtools/sha1.c b/utils/imxtools/sha1.c similarity index 100% rename from utils/sbtools/sha1.c rename to utils/imxtools/sha1.c