sbtools: refactor and cleanup

Factor common elf/sb read/write/printf routines. Factor sb zero
key, move sb version guess.

Change-Id: I5ae1885587456736e782e623610281bbee545039
This commit is contained in:
Amaury Pouly 2013-07-18 00:27:12 +02:00
parent 3c5ee9ac57
commit 1c8c24183e
12 changed files with 131 additions and 123 deletions

View file

@ -20,6 +20,7 @@
****************************************************************************/
#include "elf.h"
#include "misc.h"
#include <stdarg.h>
/**
* Definitions
@ -723,3 +724,28 @@ void elf_release(struct elf_params_t *params)
seg = next_seg;
}
}
void elf_std_printf(void *user, bool error, const char *fmt, ...)
{
if(!g_debug && !error)
return;
(void) user;
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
void elf_std_write(void *user, uint32_t addr, const void *buf, size_t count)
{
FILE *f = user;
fseek(f, addr, SEEK_SET);
fwrite(buf, count, 1, f);
}
bool elf_std_read(void *user, uint32_t addr, void *buf, size_t count)
{
if(fseek((FILE *)user, addr, SEEK_SET) == -1)
return false;
return fread(buf, 1, count, (FILE *)user) == count;
}

View file

@ -93,4 +93,10 @@ bool elf_get_start_addr(struct elf_params_t *params, uint32_t *addr);
int elf_get_nr_sections(struct elf_params_t *params);
void elf_release(struct elf_params_t *params);
/* standard implementation of read/write/printf functions
* with user being a FILE* pointer */
void elf_std_printf(void *user, bool error, const char *fmt, ...);
void elf_std_write(void *user, uint32_t addr, const void *buf, size_t count);
bool elf_std_read(void *user, uint32_t addr, void *buf, size_t count);
#endif /* __ELF_H__ */

View file

@ -52,24 +52,6 @@ int g_extern_count;
* command file to sb conversion
*/
static bool elf_read(void *user, uint32_t addr, void *buf, size_t count)
{
if(fseek((FILE *)user, addr, SEEK_SET) == -1)
return false;
return fread(buf, 1, count, (FILE *)user) == count;
}
static void elf_printf(void *user, bool error, const char *fmt, ...)
{
if(!g_debug && !error)
return;
(void) user;
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
static void resolve_extern(struct cmd_source_t *src)
{
if(!src->is_extern)
@ -102,7 +84,7 @@ static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
if(g_debug)
printf("Loading ELF file '%s'...\n", src->filename);
elf_init(&src->elf);
src->loaded = elf_read_file(&src->elf, elf_read, elf_printf, fd);
src->loaded = elf_read_file(&src->elf, elf_std_read, elf_std_printf, fd);
fclose(fd);
if(!src->loaded)
bug("error loading elf file '%s' (id '%s')\n", src->filename, id);
@ -333,12 +315,6 @@ static void usage(void)
exit(1);
}
static struct crypto_key_t g_zero_key =
{
.method = CRYPTO_KEY,
.u.key = {0}
};
int main(int argc, char **argv)
{
char *cmd_filename = NULL;
@ -385,6 +361,8 @@ int main(int argc, char **argv)
}
case 'z':
{
struct crypto_key_t g_zero_key;
sb_get_zero_key(&g_zero_key);
add_keys(&g_zero_key, 1);
break;
}
@ -407,7 +385,7 @@ int main(int argc, char **argv)
break;
}
default:
abort();
bug("Internal error: unknown option '%c'\n", c);
}
}

View file

@ -305,3 +305,44 @@ void color(color_t c)
if(g_color_enable)
printf("%s", (char *)c);
}
enum sb_version_guess_t guess_sb_version(const char *filename)
{
#define ret(x) do { fclose(f); return x; } while(0)
FILE *f = fopen(filename, "rb");
if(f == NULL)
ret(SB_VERSION_ERR);
// check signature
uint8_t sig[4];
if(fseek(f, 20, SEEK_SET))
ret(SB_VERSION_UNK);
if(fread(sig, 4, 1, f) != 1)
ret(SB_VERSION_UNK);
if(memcmp(sig, "STMP", 4) != 0)
ret(SB_VERSION_UNK);
// check header size (v1)
uint32_t hdr_size;
if(fseek(f, 8, SEEK_SET))
ret(SB_VERSION_UNK);
if(fread(&hdr_size, 4, 1, f) != 1)
ret(SB_VERSION_UNK);
if(hdr_size == 0x34)
ret(SB_VERSION_1);
// check header params relationship
struct
{
uint16_t nr_keys; /* Number of encryption keys */
uint16_t key_dict_off; /* Offset to key dictionary (in blocks) */
uint16_t header_size; /* In blocks */
uint16_t nr_sections; /* Number of sections */
uint16_t sec_hdr_size; /* Section header size (in blocks) */
} __attribute__((packed)) u;
if(fseek(f, 0x28, SEEK_SET))
ret(SB_VERSION_UNK);
if(fread(&u, sizeof(u), 1, f) != 1)
ret(SB_VERSION_UNK);
if(u.sec_hdr_size == 1 && u.header_size == 6 && u.key_dict_off == u.header_size + u.nr_sections)
ret(SB_VERSION_2);
ret(SB_VERSION_UNK);
#undef ret
}

View file

@ -63,4 +63,14 @@ extern color_t OFF, GREY, RED, GREEN, YELLOW, BLUE;
void color(color_t c);
void enable_color(bool enable);
enum sb_version_guess_t
{
SB_VERSION_1,
SB_VERSION_2,
SB_VERSION_UNK,
SB_VERSION_ERR,
};
enum sb_version_guess_t guess_sb_version(const char *filename);
#endif /* __MISC_H__ */

View file

@ -158,7 +158,7 @@ int main(int argc, char **argv)
break;
}
default:
abort();
bug("Internal error: unknown option '%c'\n", c);
}
}

View file

@ -22,6 +22,7 @@
#include <time.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
#include "misc.h"
#include "crypto.h"
#include "sb.h"
@ -1245,3 +1246,20 @@ void sb_dump(struct sb_file_t *file, void *u, sb_color_printf cprintf)
#undef printf
#undef print_hex
}
void sb_get_zero_key(struct crypto_key_t *key)
{
key->method = CRYPTO_KEY;
memset(key->u.key, 0, sizeof(key->u.key));
}
void sb_std_printf(void *user, bool error, color_t c, const char *fmt, ...)
{
(void) user;
(void) error;
va_list args;
va_start(args, fmt);
color(c);
vprintf(fmt, args);
va_end(args);
}

View file

@ -239,5 +239,9 @@ void sb_dump(struct sb_file_t *file, void *u, sb_color_printf printf);
void sb_free_instruction(struct sb_inst_t inst);
void sb_free_section(struct sb_section_t file);
void sb_free(struct sb_file_t *file);
void sb_get_zero_key(struct crypto_key_t *key);
/* standard implementation: user is unused*/
void sb_std_printf(void *user, bool error, color_t c, const char *fmt, ...);
#endif /* __SB_H__ */

View file

@ -81,7 +81,7 @@ enum sb1_error_t sb1_write_file(struct sb1_file_t *sb, const char *filename)
image_size += 8;
break;
default:
bugp("Unknown SB instruction: %#x\n", sb->insts[i].cmd);
bugp("Internal error: unknown SB instruction: %#x\n", sb->insts[i].cmd);
}
}
// now take crypto marks and sector size into account:
@ -140,7 +140,7 @@ enum sb1_error_t sb1_write_file(struct sb1_file_t *sb, const char *filename)
sb->insts[i].sdram.size_index);
break;
default:
bugp("Unknown SB instruction: %#x\n", sb->insts[i].cmd);
bugp("Internal error: unknown SB instruction: %#x\n", sb->insts[i].cmd);
}
/* handle most common cases */

View file

@ -445,6 +445,7 @@ int main(int argc, char **argv)
}
break;
default:
printf("Internal error: unknown option '%c'\n", c);
abort();
}
}

View file

@ -60,24 +60,6 @@
static char *g_out_prefix;
static bool g_elf_simplify = true;
static void elf_printf(void *user, bool error, const char *fmt, ...)
{
if(!g_debug && !error)
return;
(void) user;
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
static void elf_write(void *user, uint32_t addr, const void *buf, size_t count)
{
FILE *f = user;
fseek(f, addr, SEEK_SET);
fwrite(buf, count, 1, f);
}
static void extract_elf_section(struct elf_params_t *elf, int count, uint32_t id)
{
char name[5];
@ -94,7 +76,7 @@ static void extract_elf_section(struct elf_params_t *elf, int count, uint32_t id
return;
if(g_elf_simplify)
elf_simplify(elf);
elf_write_file(elf, elf_write, elf_printf, fd);
elf_write_file(elf, elf_std_write, elf_std_printf, fd);
fclose(fd);
}
@ -174,7 +156,7 @@ static void extract_elf(struct elf_params_t *elf, int count)
return;
if(g_elf_simplify)
elf_simplify(elf);
elf_write_file(elf, elf_write, elf_printf, fd);
elf_write_file(elf, elf_std_write, elf_std_printf, fd);
fclose(fd);
}
@ -236,73 +218,6 @@ static void usage(void)
exit(1);
}
static void sb_printf(void *user, bool error, color_t c, const char *fmt, ...)
{
(void) user;
(void) error;
va_list args;
va_start(args, fmt);
color(c);
vprintf(fmt, args);
va_end(args);
}
static struct crypto_key_t g_zero_key =
{
.method = CRYPTO_KEY,
.u.key = {0}
};
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)
{
#define ret(x) do { fclose(f); return x; } while(0)
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))
ret(SB_VERSION_UNK);
if(fread(sig, 4, 1, f) != 1)
ret(SB_VERSION_UNK);
if(memcmp(sig, "STMP", 4) != 0)
ret(SB_VERSION_UNK);
// check header size (v1)
uint32_t hdr_size;
if(fseek(f, 8, SEEK_SET))
ret(SB_VERSION_UNK);
if(fread(&hdr_size, 4, 1, f) != 1)
ret(SB_VERSION_UNK);
if(hdr_size == 0x34)
ret(SB_VERSION_1);
// check header params relationship
struct
{
uint16_t nr_keys; /* Number of encryption keys */
uint16_t key_dict_off; /* Offset to key dictionary (in blocks) */
uint16_t header_size; /* In blocks */
uint16_t nr_sections; /* Number of sections */
uint16_t sec_hdr_size; /* Section header size (in blocks) */
} __attribute__((packed)) u;
if(fseek(f, 0x28, SEEK_SET))
ret(SB_VERSION_UNK);
if(fread(&u, sizeof(u), 1, f) != 1)
ret(SB_VERSION_UNK);
if(u.sec_hdr_size == 1 && u.header_size == 6 && u.key_dict_off == u.header_size + u.nr_sections)
ret(SB_VERSION_2);
ret(SB_VERSION_UNK);
#undef ret
}
int main(int argc, char **argv)
{
bool raw_mode = false;
@ -361,8 +276,12 @@ int main(int argc, char **argv)
break;
}
case 'z':
{
struct crypto_key_t g_zero_key;
sb_get_zero_key(&g_zero_key);
add_keys(&g_zero_key, 1);
break;
}
case 'x':
{
struct crypto_key_t key;
@ -397,7 +316,7 @@ int main(int argc, char **argv)
brute_force = true;
break;
default:
abort();
bug("Internal error: unknown option '%c'\n", c);
}
}
@ -413,11 +332,16 @@ int main(int argc, char **argv)
const char *sb_filename = argv[optind];
enum sb_version_guess_t ver = guess_sb_version(sb_filename);
if(ver == SB_VERSION_ERR)
{
printf("Cannot open/read SB file: %m\n");
return 1;
}
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);
struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_std_printf, &err);
if(file == NULL)
{
color(OFF);
@ -432,7 +356,7 @@ int main(int argc, char **argv)
{
color(GREY);
printf("[Debug output]\n");
sb_dump(file, NULL, sb_printf);
sb_dump(file, NULL, sb_std_printf);
}
if(loopback)
{
@ -451,7 +375,7 @@ int main(int argc, char **argv)
{
struct crypto_key_t key;
enum sb1_error_t err;
if(!sb1_brute_force(sb_filename, NULL, sb_printf, &err, &key))
if(!sb1_brute_force(sb_filename, NULL, sb_std_printf, &err, &key))
{
color(OFF);
printf("Brute force failed: %d\n", err);
@ -475,7 +399,7 @@ int main(int argc, char **argv)
}
enum sb1_error_t err;
struct sb1_file_t *file = sb1_read_file(sb_filename, NULL, sb_printf, &err);
struct sb1_file_t *file = sb1_read_file(sb_filename, NULL, sb_std_printf, &err);
if(file == NULL)
{
color(OFF);
@ -490,7 +414,7 @@ int main(int argc, char **argv)
{
color(GREY);
printf("[Debug output]\n");
sb1_dump(file, NULL, sb_printf);
sb1_dump(file, NULL, sb_std_printf);
}
if(loopback)
sb1_write_file(file, loopback);

View file

@ -115,7 +115,7 @@ static uint32_t do_unround(union xorcrypt_key_t *key)
return 0;
}
static void test_round(union xorcrypt_key_t keys[2])
static void __attribute__((unused)) test_round(union xorcrypt_key_t keys[2])
{
union xorcrypt_key_t save[2];
memcpy(save, keys, sizeof(save));