forked from len0rd/rockbox
sbtools: factor key code, introduce crypto layer, move from open/read/... to fopen/fread/..., add support for encryption/decryption using a device when the key is not known, move sbtoelf to use getopt for command line
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30849 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
b7547e5868
commit
9fe029b12a
7 changed files with 720 additions and 312 deletions
|
|
@ -1,10 +1,22 @@
|
||||||
|
DEFINES=-DCRYPTO_LIBUSB
|
||||||
|
CC=gcc
|
||||||
|
LD=gcc
|
||||||
|
CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES)
|
||||||
|
LDFLAGS=`pkg-config --libs libusb-1.0`
|
||||||
|
|
||||||
all: elftosb sbtoelf
|
all: elftosb sbtoelf
|
||||||
|
|
||||||
sbtoelf: sbtoelf.c crc.c crypto.h aes128.c sha1.c elf.c sb.h
|
%.o: %.c
|
||||||
gcc -g -std=c99 -o $@ -W -Wall $^
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
elftosb: elftosb.c crc.c crypto.h aes128.c sha1.c elf.c sb.h dbparser.h dbparser.c
|
sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o elf.o misc.o
|
||||||
gcc -g -std=c99 -o $@ -W -Wall $^
|
$(LD) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr elftosb sbtoelf
|
rm -fr *.o
|
||||||
|
|
||||||
|
veryclean:
|
||||||
|
rm -rf sbtoelf elftosb
|
||||||
|
|
|
||||||
188
utils/sbtools/crypto.c
Normal file
188
utils/sbtools/crypto.c
Normal file
|
|
@ -0,0 +1,188 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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 "crypto.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#ifdef CRYPTO_LIBUSB
|
||||||
|
#include "libusb.h"
|
||||||
|
#endif
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
static enum crypto_method_t cur_method = CRYPTO_NONE;
|
||||||
|
static byte key[16];
|
||||||
|
static uint16_t usb_vid, usb_pid;
|
||||||
|
|
||||||
|
void crypto_setup(enum crypto_method_t method, void *param)
|
||||||
|
{
|
||||||
|
cur_method = method;
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
case CRYPTO_KEY:
|
||||||
|
memcpy(key, param, sizeof(key));
|
||||||
|
break;
|
||||||
|
case CRYPTO_USBOTP:
|
||||||
|
{
|
||||||
|
uint32_t value = *(uint32_t *)param;
|
||||||
|
usb_vid = value >> 16;
|
||||||
|
usb_pid = value & 0xffff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypto_apply(
|
||||||
|
byte *in_data, /* Input data */
|
||||||
|
byte *out_data, /* Output data (or NULL) */
|
||||||
|
int nr_blocks, /* Number of blocks (one block=16 bytes) */
|
||||||
|
byte iv[16], /* Key */
|
||||||
|
byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
|
||||||
|
int encrypt)
|
||||||
|
{
|
||||||
|
if(cur_method == CRYPTO_KEY)
|
||||||
|
{
|
||||||
|
cbc_mac(in_data, out_data, nr_blocks, key, iv, out_cbc_mac, encrypt);
|
||||||
|
return CRYPTO_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
#ifdef CRYPTO_LIBUSB
|
||||||
|
else if(cur_method == CRYPTO_USBOTP)
|
||||||
|
{
|
||||||
|
if(out_cbc_mac && !encrypt)
|
||||||
|
memcpy(*out_cbc_mac, in_data + 16 * (nr_blocks - 1), 16);
|
||||||
|
|
||||||
|
libusb_device_handle *handle = NULL;
|
||||||
|
libusb_context *ctx;
|
||||||
|
/* init library */
|
||||||
|
libusb_init(&ctx);
|
||||||
|
libusb_set_debug(NULL,3);
|
||||||
|
/* open device */
|
||||||
|
handle = libusb_open_device_with_vid_pid(ctx, usb_vid, usb_pid);
|
||||||
|
if(handle == NULL)
|
||||||
|
{
|
||||||
|
printf("usbotp: cannot open device %04x:%04x\n", usb_vid, usb_pid);
|
||||||
|
return CRYPTO_ERROR_NODEVICE;
|
||||||
|
}
|
||||||
|
/* get device pointer */
|
||||||
|
libusb_device *mydev = libusb_get_device(handle);
|
||||||
|
if(g_debug)
|
||||||
|
printf("usbotp: device found at %d:%d\n", libusb_get_bus_number(mydev),
|
||||||
|
libusb_get_device_address(mydev));
|
||||||
|
int config_id;
|
||||||
|
/* explore configuration */
|
||||||
|
libusb_get_configuration(handle, &config_id);
|
||||||
|
struct libusb_config_descriptor *config;
|
||||||
|
libusb_get_active_config_descriptor(mydev, &config);
|
||||||
|
|
||||||
|
if(g_debug)
|
||||||
|
{
|
||||||
|
printf("usbotp: configuration: %d\n", config_id);
|
||||||
|
printf("usbotp: interfaces: %d\n", config->bNumInterfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct libusb_endpoint_descriptor *endp = NULL;
|
||||||
|
int intf, intf_alt;
|
||||||
|
for(intf = 0; intf < config->bNumInterfaces; intf++)
|
||||||
|
for(intf_alt = 0; intf_alt < config->interface[intf].num_altsetting; intf_alt++)
|
||||||
|
for(int ep = 0; ep < config->interface[intf].altsetting[intf_alt].bNumEndpoints; ep++)
|
||||||
|
{
|
||||||
|
endp = &config->interface[intf].altsetting[intf_alt].endpoint[ep];
|
||||||
|
if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT &&
|
||||||
|
(endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
|
||||||
|
goto Lfound;
|
||||||
|
}
|
||||||
|
libusb_close(handle);
|
||||||
|
printf("usbotp: No suitable endpoint found\n");
|
||||||
|
return CRYPTO_ERROR_BADENDP;
|
||||||
|
|
||||||
|
if(g_debug)
|
||||||
|
{
|
||||||
|
printf("usbotp: use interface %d, alt %d\n", intf, intf_alt);
|
||||||
|
printf("usbotp: use endpoint %d\n", endp->bEndpointAddress);
|
||||||
|
}
|
||||||
|
Lfound:
|
||||||
|
if(libusb_claim_interface(handle, intf) != 0)
|
||||||
|
{
|
||||||
|
if(g_debug)
|
||||||
|
printf("usbotp: claim error\n");
|
||||||
|
return CRYPTO_ERROR_CLAIMFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int buffer_size = 16 + 16 * nr_blocks;
|
||||||
|
unsigned char *buffer = xmalloc(buffer_size);
|
||||||
|
memcpy(buffer, iv, 16);
|
||||||
|
memcpy(buffer + 16, in_data, 16 * nr_blocks);
|
||||||
|
int ret = libusb_control_transfer(handle,
|
||||||
|
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE,
|
||||||
|
0xaa, encrypt ? 0xeeee : 0xdddd, 0, buffer, buffer_size, 1000);
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
if(g_debug)
|
||||||
|
printf("usbotp: control transfer failed: %d\n", ret);
|
||||||
|
libusb_release_interface(handle, intf);
|
||||||
|
libusb_close(handle);
|
||||||
|
return CRYPTO_ERROR_DEVREJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int recv_size;
|
||||||
|
ret = libusb_interrupt_transfer(handle, endp->bEndpointAddress, buffer,
|
||||||
|
buffer_size, &recv_size, 1000);
|
||||||
|
libusb_release_interface(handle, intf);
|
||||||
|
libusb_close(handle);
|
||||||
|
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
if(g_debug)
|
||||||
|
printf("usbotp: interrupt transfer failed: %d\n", ret);
|
||||||
|
return CRYPTO_ERROR_DEVSILENT;
|
||||||
|
}
|
||||||
|
if(recv_size != buffer_size)
|
||||||
|
{
|
||||||
|
if(g_debug)
|
||||||
|
printf("usbotp: device returned %d bytes, expected %d\n", recv_size,
|
||||||
|
buffer_size);
|
||||||
|
return CRYPTO_ERROR_DEVERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(out_data)
|
||||||
|
memcpy(out_data, buffer + 16, 16 * nr_blocks);
|
||||||
|
if(out_cbc_mac && encrypt)
|
||||||
|
memcpy(*out_cbc_mac, buffer + buffer_size - 16, 16);
|
||||||
|
|
||||||
|
return CRYPTO_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return CRYPTO_ERROR_BADSETUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypto_cbc(
|
||||||
|
byte *in_data, /* Input data */
|
||||||
|
byte *out_data, /* Output data (or NULL) */
|
||||||
|
int nr_blocks, /* Number of blocks (one block=16 bytes) */
|
||||||
|
struct crypto_key_t *key, /* Key */
|
||||||
|
byte iv[16], /* IV */
|
||||||
|
byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
|
||||||
|
int encrypt)
|
||||||
|
{
|
||||||
|
crypto_setup(key->method, (void *)key->u.param);
|
||||||
|
return crypto_apply(in_data, out_data, nr_blocks, iv, out_cbc_mac, encrypt);
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,9 @@
|
||||||
* KIND, either express or implied.
|
* KIND, either express or implied.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
#ifndef __CRYPTO_H__
|
||||||
|
#define __CRYPTO_H__
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -39,6 +42,57 @@ void cbc_mac(
|
||||||
int encrypt /* 1 to encrypt, 0 to decrypt */
|
int encrypt /* 1 to encrypt, 0 to decrypt */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* crypto.c */
|
||||||
|
enum crypto_method_t
|
||||||
|
{
|
||||||
|
CRYPTO_NONE, /* disable */
|
||||||
|
CRYPTO_KEY, /* key */
|
||||||
|
CRYPTO_USBOTP, /* use usbotp device */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* parameter can be:
|
||||||
|
* - CRYPTO_KEY: array of 16-bytes (the key)
|
||||||
|
* - CRYPTO_USBOTP: 32-bit integer: vid << 16 | pid */
|
||||||
|
void crypto_setup(enum crypto_method_t method, void *param);
|
||||||
|
|
||||||
|
#define CRYPTO_ERROR_SUCCESS 0
|
||||||
|
#define CRYPTO_ERROR_BADSETUP -1 /* bad crypto setup */
|
||||||
|
#define CRYPTO_ERROR_NODEVICE -2 /* no device with vid:pid */
|
||||||
|
#define CRYPTO_ERROR_BADENDP -3 /* device doesn't have the required endpoints */
|
||||||
|
#define CRYPTO_ERROR_CLAIMFAIL -4 /* device interface claim error */
|
||||||
|
#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) */
|
||||||
|
/* return 0 on success, <0 on error */
|
||||||
|
int crypto_apply(
|
||||||
|
byte *in_data, /* Input data */
|
||||||
|
byte *out_data, /* Output data (or NULL) */
|
||||||
|
int nr_blocks, /* Number of blocks (one block=16 bytes) */
|
||||||
|
byte iv[16], /* IV */
|
||||||
|
byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
|
||||||
|
int encrypt);
|
||||||
|
|
||||||
|
/* all-in-one function */
|
||||||
|
struct crypto_key_t
|
||||||
|
{
|
||||||
|
enum crypto_method_t method;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
byte key[16];
|
||||||
|
uint32_t vid_pid;
|
||||||
|
byte param[0];
|
||||||
|
}u;
|
||||||
|
};
|
||||||
|
|
||||||
|
int crypto_cbc(
|
||||||
|
byte *in_data, /* Input data */
|
||||||
|
byte *out_data, /* Output data (or NULL) */
|
||||||
|
int nr_blocks, /* Number of blocks (one block=16 bytes) */
|
||||||
|
struct crypto_key_t *key, /* Key */
|
||||||
|
byte iv[16], /* IV */
|
||||||
|
byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
|
||||||
|
int encrypt);
|
||||||
|
|
||||||
/* crc.c */
|
/* crc.c */
|
||||||
uint32_t crc(byte *data, int size);
|
uint32_t crc(byte *data, int size);
|
||||||
uint32_t crc_continue(uint32_t previous_crc, byte *data, int size);
|
uint32_t crc_continue(uint32_t previous_crc, byte *data, int size);
|
||||||
|
|
@ -56,3 +110,5 @@ void sha_1_block(struct sha_1_params_t *params, uint32_t cur_hash[5], byte *data
|
||||||
void sha_1_update(struct sha_1_params_t *params, byte *buffer, int size);
|
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_finish(struct sha_1_params_t *params);
|
||||||
void sha_1_output(struct sha_1_params_t *params, byte *out);
|
void sha_1_output(struct sha_1_params_t *params, byte *out);
|
||||||
|
|
||||||
|
#endif /* __CRYPTO_H__ */
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,8 @@
|
||||||
|
|
||||||
#define _ISOC99_SOURCE
|
#define _ISOC99_SOURCE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
@ -39,143 +34,18 @@
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "sb.h"
|
#include "sb.h"
|
||||||
#include "dbparser.h"
|
#include "dbparser.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
#define _STR(a) #a
|
|
||||||
#define STR(a) _STR(a)
|
|
||||||
|
|
||||||
#define bug(...) do { fprintf(stderr,"["__FILE__":"STR(__LINE__)"]ERROR: "__VA_ARGS__); exit(1); } while(0)
|
|
||||||
#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0)
|
|
||||||
|
|
||||||
bool g_debug = false;
|
|
||||||
char **g_extern;
|
char **g_extern;
|
||||||
int g_extern_count;
|
int g_extern_count;
|
||||||
|
|
||||||
#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
|
#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
|
||||||
|
|
||||||
/**
|
#define crypto_cbc(...) \
|
||||||
* Misc
|
do { int ret = crypto_cbc(__VA_ARGS__); \
|
||||||
*/
|
if(ret != CRYPTO_ERROR_SUCCESS) \
|
||||||
|
bug("crypto_cbc error: %d\n", ret); \
|
||||||
char *s_getenv(const char *name)
|
}while(0)
|
||||||
{
|
|
||||||
char *s = getenv(name);
|
|
||||||
return s ? s : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void generate_random_data(void *buf, size_t sz)
|
|
||||||
{
|
|
||||||
static int rand_fd = -1;
|
|
||||||
if(rand_fd == -1)
|
|
||||||
rand_fd = open("/dev/urandom", O_RDONLY);
|
|
||||||
if(rand_fd == -1)
|
|
||||||
bugp("failed to open /dev/urandom");
|
|
||||||
if(read(rand_fd, buf, sz) != (ssize_t)sz)
|
|
||||||
bugp("failed to read /dev/urandom");
|
|
||||||
}
|
|
||||||
|
|
||||||
void *xmalloc(size_t s) /* malloc helper, used in elf.c */
|
|
||||||
{
|
|
||||||
void * r = malloc(s);
|
|
||||||
if(!r) bugp("malloc");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
int convxdigit(char digit, byte *val)
|
|
||||||
{
|
|
||||||
if(digit >= '0' && digit <= '9')
|
|
||||||
{
|
|
||||||
*val = digit - '0';
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if(digit >= 'A' && digit <= 'F')
|
|
||||||
{
|
|
||||||
*val = digit - 'A' + 10;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if(digit >= 'a' && digit <= 'f')
|
|
||||||
{
|
|
||||||
*val = digit - 'a' + 10;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key file parsing
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef byte (*key_array_t)[16];
|
|
||||||
|
|
||||||
int g_nr_keys;
|
|
||||||
key_array_t g_key_array;
|
|
||||||
|
|
||||||
static void add_keys(key_array_t ka, int kac)
|
|
||||||
{
|
|
||||||
key_array_t new_ka = xmalloc((g_nr_keys + kac) * 16);
|
|
||||||
memcpy(new_ka, g_key_array, g_nr_keys * 16);
|
|
||||||
memcpy(new_ka + g_nr_keys, ka, kac * 16);
|
|
||||||
free(g_key_array);
|
|
||||||
g_key_array = new_ka;
|
|
||||||
g_nr_keys += kac;
|
|
||||||
}
|
|
||||||
|
|
||||||
static key_array_t read_keys(const char *key_file, int *num_keys)
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
struct stat st;
|
|
||||||
int fd = open(key_file,O_RDONLY);
|
|
||||||
if(fd == -1)
|
|
||||||
bugp("opening key file failed");
|
|
||||||
if(fstat(fd,&st) == -1)
|
|
||||||
bugp("key file stat() failed");
|
|
||||||
size = st.st_size;
|
|
||||||
char *buf = xmalloc(size);
|
|
||||||
if(read(fd, buf, size) != (ssize_t)size)
|
|
||||||
bugp("reading key file");
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
if(g_debug)
|
|
||||||
printf("Parsing key file '%s'...\n", key_file);
|
|
||||||
*num_keys = size ? 1 : 0;
|
|
||||||
char *ptr = buf;
|
|
||||||
/* allow trailing newline at the end (but no space after it) */
|
|
||||||
while(ptr != buf + size && (ptr + 1) != buf + size)
|
|
||||||
{
|
|
||||||
if(*ptr++ == '\n')
|
|
||||||
(*num_keys)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
key_array_t keys = xmalloc(sizeof(byte[16]) * *num_keys);
|
|
||||||
int pos = 0;
|
|
||||||
for(int i = 0; i < *num_keys; i++)
|
|
||||||
{
|
|
||||||
/* skip ws */
|
|
||||||
while(pos < size && isspace(buf[pos]))
|
|
||||||
pos++;
|
|
||||||
/* enough space ? */
|
|
||||||
if((pos + 32) > size)
|
|
||||||
bugp("invalid key file");
|
|
||||||
for(int j = 0; j < 16; j++)
|
|
||||||
{
|
|
||||||
byte a, b;
|
|
||||||
if(convxdigit(buf[pos + 2 * j], &a) || convxdigit(buf[pos + 2 * j + 1], &b))
|
|
||||||
bugp(" invalid key, it should be a 128-bit key written in hexadecimal\n");
|
|
||||||
keys[i][j] = (a << 4) | b;
|
|
||||||
}
|
|
||||||
if(g_debug)
|
|
||||||
{
|
|
||||||
printf("Add key: ");
|
|
||||||
for(int j = 0; j < 16; j++)
|
|
||||||
printf("%02x", keys[i][j]);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
pos += 32;
|
|
||||||
}
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* command file to sb conversion
|
* command file to sb conversion
|
||||||
|
|
@ -224,9 +94,9 @@ struct sb_file_t
|
||||||
|
|
||||||
static bool elf_read(void *user, uint32_t addr, void *buf, size_t count)
|
static bool elf_read(void *user, uint32_t addr, void *buf, size_t count)
|
||||||
{
|
{
|
||||||
if(lseek(*(int *)user, addr, SEEK_SET) == (off_t)-1)
|
if(fseek((FILE *)user, addr, SEEK_SET) == -1)
|
||||||
return false;
|
return false;
|
||||||
return read(*(int *)user, buf, count) == (ssize_t)count;
|
return fread(buf, 1, count, (FILE *)user) == count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void elf_printf(void *user, bool error, const char *fmt, ...)
|
static void elf_printf(void *user, bool error, const char *fmt, ...)
|
||||||
|
|
@ -264,14 +134,14 @@ static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
|
||||||
resolve_extern(src);
|
resolve_extern(src);
|
||||||
/* load it */
|
/* load it */
|
||||||
src->type = CMD_SRC_ELF;
|
src->type = CMD_SRC_ELF;
|
||||||
int fd = open(src->filename, O_RDONLY);
|
FILE *fd = fopen(src->filename, "rb");
|
||||||
if(fd < 0)
|
if(fd == NULL)
|
||||||
bug("cannot open '%s' (id '%s')\n", src->filename, id);
|
bug("cannot open '%s' (id '%s')\n", src->filename, id);
|
||||||
if(g_debug)
|
if(g_debug)
|
||||||
printf("Loading ELF file '%s'...\n", src->filename);
|
printf("Loading ELF file '%s'...\n", src->filename);
|
||||||
elf_init(&src->elf);
|
elf_init(&src->elf);
|
||||||
src->loaded = elf_read_file(&src->elf, elf_read, elf_printf, &fd);
|
src->loaded = elf_read_file(&src->elf, elf_read, elf_printf, fd);
|
||||||
close(fd);
|
fclose(fd);
|
||||||
if(!src->loaded)
|
if(!src->loaded)
|
||||||
bug("error loading elf file '%s' (id '%s')\n", src->filename, id);
|
bug("error loading elf file '%s' (id '%s')\n", src->filename, id);
|
||||||
elf_translate_addresses(&src->elf);
|
elf_translate_addresses(&src->elf);
|
||||||
|
|
@ -291,16 +161,17 @@ static void load_bin_by_id(struct cmd_file_t *cmd_file, const char *id)
|
||||||
resolve_extern(src);
|
resolve_extern(src);
|
||||||
/* load it */
|
/* load it */
|
||||||
src->type = CMD_SRC_BIN;
|
src->type = CMD_SRC_BIN;
|
||||||
int fd = open(src->filename, O_RDONLY);
|
FILE *fd = fopen(src->filename, "rb");
|
||||||
if(fd < 0)
|
if(fd == NULL)
|
||||||
bug("cannot open '%s' (id '%s')\n", src->filename, id);
|
bug("cannot open '%s' (id '%s')\n", src->filename, id);
|
||||||
if(g_debug)
|
if(g_debug)
|
||||||
printf("Loading BIN file '%s'...\n", src->filename);
|
printf("Loading BIN file '%s'...\n", src->filename);
|
||||||
src->bin.size = lseek(fd, 0, SEEK_END);
|
fseek(fd, 0, SEEK_END);
|
||||||
lseek(fd, 0, SEEK_SET);
|
src->bin.size = ftell(fd);
|
||||||
|
fseek(fd, 0, SEEK_SET);
|
||||||
src->bin.data = xmalloc(src->bin.size);
|
src->bin.data = xmalloc(src->bin.size);
|
||||||
read(fd, src->bin.data, src->bin.size);
|
fread(src->bin.data, 1, src->bin.size, fd);
|
||||||
close(fd);
|
fclose(fd);
|
||||||
src->loaded = true;
|
src->loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -767,12 +638,12 @@ void produce_sb_instruction(struct sb_inst_t *inst,
|
||||||
|
|
||||||
static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
||||||
{
|
{
|
||||||
int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT,
|
FILE *fd = fopen(filename, "wb");
|
||||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
if(fd == NULL)
|
||||||
if(fd < 0)
|
|
||||||
bugp("cannot open output file");
|
bugp("cannot open output file");
|
||||||
|
|
||||||
byte real_key[16];
|
struct crypto_key_t real_key;
|
||||||
|
real_key.method = CRYPTO_KEY;
|
||||||
byte crypto_iv[16];
|
byte crypto_iv[16];
|
||||||
byte (*cbc_macs)[16] = xmalloc(16 * g_nr_keys);
|
byte (*cbc_macs)[16] = xmalloc(16 * g_nr_keys);
|
||||||
/* init CBC-MACs */
|
/* init CBC-MACs */
|
||||||
|
|
@ -782,7 +653,7 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
||||||
fill_gaps(sb);
|
fill_gaps(sb);
|
||||||
compute_sb_offsets(sb);
|
compute_sb_offsets(sb);
|
||||||
|
|
||||||
generate_random_data(real_key, sizeof(real_key));
|
generate_random_data(real_key.u.key, 16);
|
||||||
|
|
||||||
/* global SHA-1 */
|
/* global SHA-1 */
|
||||||
struct sha_1_params_t file_sha1;
|
struct sha_1_params_t file_sha1;
|
||||||
|
|
@ -791,13 +662,13 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
||||||
struct sb_header_t sb_hdr;
|
struct sb_header_t sb_hdr;
|
||||||
produce_sb_header(sb, &sb_hdr);
|
produce_sb_header(sb, &sb_hdr);
|
||||||
sha_1_update(&file_sha1, (byte *)&sb_hdr, sizeof(sb_hdr));
|
sha_1_update(&file_sha1, (byte *)&sb_hdr, sizeof(sb_hdr));
|
||||||
write(fd, &sb_hdr, sizeof(sb_hdr));
|
fwrite(&sb_hdr, 1, sizeof(sb_hdr), fd);
|
||||||
|
|
||||||
memcpy(crypto_iv, &sb_hdr, 16);
|
memcpy(crypto_iv, &sb_hdr, 16);
|
||||||
|
|
||||||
/* update CBC-MACs */
|
/* update CBC-MACs */
|
||||||
for(int i = 0; i < g_nr_keys; i++)
|
for(int i = 0; i < g_nr_keys; i++)
|
||||||
cbc_mac((byte *)&sb_hdr, NULL, sizeof(sb_hdr) / BLOCK_SIZE, g_key_array[i],
|
crypto_cbc((byte *)&sb_hdr, NULL, sizeof(sb_hdr) / BLOCK_SIZE, &g_key_array[i],
|
||||||
cbc_macs[i], &cbc_macs[i], 1);
|
cbc_macs[i], &cbc_macs[i], 1);
|
||||||
|
|
||||||
/* produce and write section headers */
|
/* produce and write section headers */
|
||||||
|
|
@ -806,21 +677,21 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
||||||
struct sb_section_header_t sb_sec_hdr;
|
struct sb_section_header_t sb_sec_hdr;
|
||||||
produce_sb_section_header(&sb->sections[i], &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));
|
sha_1_update(&file_sha1, (byte *)&sb_sec_hdr, sizeof(sb_sec_hdr));
|
||||||
write(fd, &sb_sec_hdr, sizeof(sb_sec_hdr));
|
fwrite(&sb_sec_hdr, 1, sizeof(sb_sec_hdr), fd);
|
||||||
/* update CBC-MACs */
|
/* update CBC-MACs */
|
||||||
for(int j = 0; j < g_nr_keys; j++)
|
for(int j = 0; j < g_nr_keys; j++)
|
||||||
cbc_mac((byte *)&sb_sec_hdr, NULL, sizeof(sb_sec_hdr) / BLOCK_SIZE,
|
crypto_cbc((byte *)&sb_sec_hdr, NULL, sizeof(sb_sec_hdr) / BLOCK_SIZE,
|
||||||
g_key_array[j], cbc_macs[j], &cbc_macs[j], 1);
|
&g_key_array[j], cbc_macs[j], &cbc_macs[j], 1);
|
||||||
}
|
}
|
||||||
/* produce key dictionary */
|
/* produce key dictionary */
|
||||||
for(int i = 0; i < g_nr_keys; i++)
|
for(int i = 0; i < g_nr_keys; i++)
|
||||||
{
|
{
|
||||||
struct sb_key_dictionary_entry_t entry;
|
struct sb_key_dictionary_entry_t entry;
|
||||||
memcpy(entry.hdr_cbc_mac, cbc_macs[i], 16);
|
memcpy(entry.hdr_cbc_mac, cbc_macs[i], 16);
|
||||||
cbc_mac(real_key, entry.key, sizeof(real_key) / BLOCK_SIZE, g_key_array[i],
|
crypto_cbc(real_key.u.key, entry.key, 1, &g_key_array[i],
|
||||||
crypto_iv, NULL, 1);
|
crypto_iv, NULL, 1);
|
||||||
|
|
||||||
write(fd, &entry, sizeof(entry));
|
fwrite(&entry, 1, sizeof(entry), fd);
|
||||||
sha_1_update(&file_sha1, (byte *)&entry, sizeof(entry));
|
sha_1_update(&file_sha1, (byte *)&entry, sizeof(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -836,7 +707,7 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
||||||
byte a, b;
|
byte a, b;
|
||||||
if(convxdigit(key[2 * i], &a) || convxdigit(key[2 * i + 1], &b))
|
if(convxdigit(key[2 * i], &a) || convxdigit(key[2 * i + 1], &b))
|
||||||
bugp("Cannot override real key: key should be a 128-bit key written in hexadecimal\n");
|
bugp("Cannot override real key: key should be a 128-bit key written in hexadecimal\n");
|
||||||
real_key[i] = (a << 4) | b;
|
real_key.u.key[i] = (a << 4) | b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(strlen(s_getenv("SB_OVERRIDE_IV")) != 0)
|
if(strlen(s_getenv("SB_OVERRIDE_IV")) != 0)
|
||||||
|
|
@ -858,7 +729,7 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
||||||
{
|
{
|
||||||
printf("Real key: ");
|
printf("Real key: ");
|
||||||
for(int j = 0; j < 16; j++)
|
for(int j = 0; j < 16; j++)
|
||||||
printf("%02x", real_key[j]);
|
printf("%02x", real_key.u.key[j]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("IV : ");
|
printf("IV : ");
|
||||||
for(int j = 0; j < 16; j++)
|
for(int j = 0; j < 16; j++)
|
||||||
|
|
@ -872,10 +743,10 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
||||||
struct sb_instruction_tag_t tag_cmd;
|
struct sb_instruction_tag_t tag_cmd;
|
||||||
produce_section_tag_cmd(&sb->sections[i], &tag_cmd, (i + 1) == sb_hdr.nr_sections);
|
produce_section_tag_cmd(&sb->sections[i], &tag_cmd, (i + 1) == sb_hdr.nr_sections);
|
||||||
if(g_nr_keys > 0)
|
if(g_nr_keys > 0)
|
||||||
cbc_mac((byte *)&tag_cmd, (byte *)&tag_cmd, sizeof(tag_cmd) / BLOCK_SIZE,
|
crypto_cbc((byte *)&tag_cmd, (byte *)&tag_cmd, sizeof(tag_cmd) / BLOCK_SIZE,
|
||||||
real_key, crypto_iv, NULL, 1);
|
&real_key, crypto_iv, NULL, 1);
|
||||||
sha_1_update(&file_sha1, (byte *)&tag_cmd, sizeof(tag_cmd));
|
sha_1_update(&file_sha1, (byte *)&tag_cmd, sizeof(tag_cmd));
|
||||||
write(fd, &tag_cmd, sizeof(tag_cmd));
|
fwrite(&tag_cmd, 1, sizeof(tag_cmd), fd);
|
||||||
/* produce other commands */
|
/* produce other commands */
|
||||||
byte cur_cbc_mac[16];
|
byte cur_cbc_mac[16];
|
||||||
memcpy(cur_cbc_mac, crypto_iv, 16);
|
memcpy(cur_cbc_mac, crypto_iv, 16);
|
||||||
|
|
@ -888,10 +759,10 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
||||||
struct sb_instruction_common_t cmd;
|
struct sb_instruction_common_t cmd;
|
||||||
produce_sb_instruction(inst, &cmd);
|
produce_sb_instruction(inst, &cmd);
|
||||||
if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
|
if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
|
||||||
cbc_mac((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE,
|
crypto_cbc((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE,
|
||||||
real_key, cur_cbc_mac, &cur_cbc_mac, 1);
|
&real_key, cur_cbc_mac, &cur_cbc_mac, 1);
|
||||||
sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd));
|
sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd));
|
||||||
write(fd, &cmd, sizeof(cmd));
|
fwrite(&cmd, 1, sizeof(cmd), fd);
|
||||||
}
|
}
|
||||||
/* data */
|
/* data */
|
||||||
if(inst->inst == SB_INST_LOAD || inst->inst == SB_INST_DATA)
|
if(inst->inst == SB_INST_LOAD || inst->inst == SB_INST_DATA)
|
||||||
|
|
@ -901,10 +772,10 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
||||||
memcpy(data, inst->data, inst->size);
|
memcpy(data, inst->data, inst->size);
|
||||||
memcpy(data + inst->size, inst->padding, inst->padding_size);
|
memcpy(data + inst->size, inst->padding, inst->padding_size);
|
||||||
if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
|
if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
|
||||||
cbc_mac(data, data, sz / BLOCK_SIZE,
|
crypto_cbc(data, data, sz / BLOCK_SIZE,
|
||||||
real_key, cur_cbc_mac, &cur_cbc_mac, 1);
|
&real_key, cur_cbc_mac, &cur_cbc_mac, 1);
|
||||||
sha_1_update(&file_sha1, data, sz);
|
sha_1_update(&file_sha1, data, sz);
|
||||||
write(fd, data, sz);
|
fwrite(data, 1, sz, fd);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -915,10 +786,10 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename)
|
||||||
sha_1_output(&file_sha1, final_sig);
|
sha_1_output(&file_sha1, final_sig);
|
||||||
generate_random_data(final_sig + 20, 12);
|
generate_random_data(final_sig + 20, 12);
|
||||||
if(g_nr_keys > 0)
|
if(g_nr_keys > 0)
|
||||||
cbc_mac(final_sig, final_sig, 2, real_key, crypto_iv, NULL, 1);
|
crypto_cbc(final_sig, final_sig, 2, &real_key, crypto_iv, NULL, 1);
|
||||||
write(fd, final_sig, 32);
|
fwrite(final_sig, 1, 32, fd);
|
||||||
|
|
||||||
close(fd);
|
fclose(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usage(void)
|
void usage(void)
|
||||||
|
|
@ -931,10 +802,16 @@ void usage(void)
|
||||||
printf(" -d/--debug\tEnable debug output\n");
|
printf(" -d/--debug\tEnable debug output\n");
|
||||||
printf(" -k <file>\tAdd key file\n");
|
printf(" -k <file>\tAdd key file\n");
|
||||||
printf(" -z\t\tAdd zero key\n");
|
printf(" -z\t\tAdd zero key\n");
|
||||||
|
printf(" --single-key <key>\tAdd single key\n");
|
||||||
|
printf(" --usb-otp <vid>:<pid>\tAdd USB OTP device\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte g_zero_key[16] = {0};
|
static struct crypto_key_t g_zero_key =
|
||||||
|
{
|
||||||
|
.method = CRYPTO_KEY,
|
||||||
|
.u.key = {0}
|
||||||
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
@ -947,6 +824,8 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
{"help", no_argument, 0, '?'},
|
{"help", no_argument, 0, '?'},
|
||||||
{"debug", no_argument, 0, 'd'},
|
{"debug", no_argument, 0, 'd'},
|
||||||
|
{"single-key", required_argument, 0, 's'},
|
||||||
|
{"usb-otp", required_argument, 0, 'u'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -979,6 +858,42 @@ int main(int argc, char **argv)
|
||||||
add_keys(&g_zero_key, 1);
|
add_keys(&g_zero_key, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 's':
|
||||||
|
{
|
||||||
|
struct crypto_key_t key;
|
||||||
|
key.method = CRYPTO_KEY;
|
||||||
|
if(strlen(optarg) != 32)
|
||||||
|
bug("The key given in argument is invalid");
|
||||||
|
for(int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
byte a, b;
|
||||||
|
if(convxdigit(optarg[2 * i], &a) || convxdigit(optarg[2 * i + 1], &b))
|
||||||
|
bugp("The key given in argument is invalid\n");
|
||||||
|
key.u.key[i] = (a << 4) | b;
|
||||||
|
}
|
||||||
|
add_keys(&key, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u':
|
||||||
|
{
|
||||||
|
int vid, pid;
|
||||||
|
char *p = strchr(optarg, ':');
|
||||||
|
if(p == NULL)
|
||||||
|
bug("Invalid VID/PID\n");
|
||||||
|
|
||||||
|
char *end;
|
||||||
|
vid = strtol(optarg, &end, 16);
|
||||||
|
if(end != p)
|
||||||
|
bug("Invalid VID/PID\n");
|
||||||
|
pid = strtol(p + 1, &end, 16);
|
||||||
|
if(end != (optarg + strlen(optarg)))
|
||||||
|
bug("Invalid VID/PID\n");
|
||||||
|
struct crypto_key_t key;
|
||||||
|
key.method = CRYPTO_USBOTP;
|
||||||
|
key.u.vid_pid = vid << 16 | pid;
|
||||||
|
add_keys(&key, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
@ -997,9 +912,8 @@ int main(int argc, char **argv)
|
||||||
printf("key: %d\n", g_nr_keys);
|
printf("key: %d\n", g_nr_keys);
|
||||||
for(int i = 0; i < g_nr_keys; i++)
|
for(int i = 0; i < g_nr_keys; i++)
|
||||||
{
|
{
|
||||||
for(int j = 0; j < 16; j++)
|
printf(" ");
|
||||||
printf(" %02x", g_key_array[i][j]);
|
print_key(&g_key_array[i], true);
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < g_extern_count; i++)
|
for(int i = 0; i < g_extern_count; i++)
|
||||||
|
|
|
||||||
174
utils/sbtools/misc.c
Normal file
174
utils/sbtools/misc.c
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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 <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
bool g_debug = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Misc
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *s_getenv(const char *name)
|
||||||
|
{
|
||||||
|
char *s = getenv(name);
|
||||||
|
return s ? s : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_random_data(void *buf, size_t sz)
|
||||||
|
{
|
||||||
|
FILE *rand_fd = fopen("/dev/urandom", "rb");
|
||||||
|
if(rand_fd == NULL)
|
||||||
|
bugp("failed to open /dev/urandom");
|
||||||
|
if(fread(buf, 1, sz, rand_fd) != sz)
|
||||||
|
bugp("failed to read /dev/urandom");
|
||||||
|
fclose(rand_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *xmalloc(size_t s)
|
||||||
|
{
|
||||||
|
void * r = malloc(s);
|
||||||
|
if(!r) bugp("malloc");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int convxdigit(char digit, byte *val)
|
||||||
|
{
|
||||||
|
if(digit >= '0' && digit <= '9')
|
||||||
|
{
|
||||||
|
*val = digit - '0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(digit >= 'A' && digit <= 'F')
|
||||||
|
{
|
||||||
|
*val = digit - 'A' + 10;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(digit >= 'a' && digit <= 'f')
|
||||||
|
{
|
||||||
|
*val = digit - 'a' + 10;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key file parsing
|
||||||
|
*/
|
||||||
|
int g_nr_keys;
|
||||||
|
key_array_t g_key_array;
|
||||||
|
|
||||||
|
void add_keys(key_array_t ka, int kac)
|
||||||
|
{
|
||||||
|
key_array_t new_ka = xmalloc((g_nr_keys + kac) * sizeof(struct crypto_key_t));
|
||||||
|
memcpy(new_ka, g_key_array, g_nr_keys * sizeof(struct crypto_key_t));
|
||||||
|
memcpy(new_ka + g_nr_keys, ka, kac * sizeof(struct crypto_key_t));
|
||||||
|
free(g_key_array);
|
||||||
|
g_key_array = new_ka;
|
||||||
|
g_nr_keys += kac;
|
||||||
|
}
|
||||||
|
|
||||||
|
key_array_t read_keys(const char *key_file, int *num_keys)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
FILE *fd = fopen(key_file, "r");
|
||||||
|
if(fd == NULL)
|
||||||
|
bugp("opening key file failed");
|
||||||
|
fseek(fd, 0, SEEK_END);
|
||||||
|
size = ftell(fd);
|
||||||
|
fseek(fd, 0, SEEK_SET);
|
||||||
|
char *buf = xmalloc(size);
|
||||||
|
if(fread(buf, size, 1, fd) != (size_t)size)
|
||||||
|
bugp("reading key file");
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
if(g_debug)
|
||||||
|
printf("Parsing key file '%s'...\n", key_file);
|
||||||
|
*num_keys = size ? 1 : 0;
|
||||||
|
char *ptr = buf;
|
||||||
|
/* allow trailing newline at the end (but no space after it) */
|
||||||
|
while(ptr != buf + size && (ptr + 1) != buf + size)
|
||||||
|
{
|
||||||
|
if(*ptr++ == '\n')
|
||||||
|
(*num_keys)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
key_array_t keys = xmalloc(sizeof(struct crypto_key_t) * *num_keys);
|
||||||
|
int pos = 0;
|
||||||
|
for(int i = 0; i < *num_keys; i++)
|
||||||
|
{
|
||||||
|
/* skip ws */
|
||||||
|
while(pos < size && isspace(buf[pos]))
|
||||||
|
pos++;
|
||||||
|
/* enough space ? */
|
||||||
|
if((pos + 32) > size)
|
||||||
|
bugp("invalid key file");
|
||||||
|
keys[i].method = CRYPTO_KEY;
|
||||||
|
for(int j = 0; j < 16; j++)
|
||||||
|
{
|
||||||
|
byte a, b;
|
||||||
|
if(convxdigit(buf[pos + 2 * j], &a) || convxdigit(buf[pos + 2 * j + 1], &b))
|
||||||
|
bugp(" invalid key, it should be a 128-bit key written in hexadecimal\n");
|
||||||
|
keys[i].u.key[j] = (a << 4) | b;
|
||||||
|
}
|
||||||
|
if(g_debug)
|
||||||
|
{
|
||||||
|
printf("Add key: ");
|
||||||
|
for(int j = 0; j < 16; j++)
|
||||||
|
printf("%02x", keys[i].u.key[j]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
pos += 32;
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_hex(byte *data, int len, bool newline)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < len; i++)
|
||||||
|
printf("%02X ", data[i]);
|
||||||
|
if(newline)
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_key(struct crypto_key_t *key, bool newline)
|
||||||
|
{
|
||||||
|
switch(key->method)
|
||||||
|
{
|
||||||
|
case CRYPTO_KEY:
|
||||||
|
print_hex(key->u.key, 16, false);
|
||||||
|
break;
|
||||||
|
case CRYPTO_USBOTP:
|
||||||
|
printf("USB-OTP(%04x:%04x)", key->u.vid_pid >> 16, key->u.vid_pid & 0xffff);
|
||||||
|
break;
|
||||||
|
case CRYPTO_NONE:
|
||||||
|
printf("none");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(newline)
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
48
utils/sbtools/misc.h
Normal file
48
utils/sbtools/misc.h
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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 __MISC_H__
|
||||||
|
#define __MISC_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "crypto.h"
|
||||||
|
|
||||||
|
#define _STR(a) #a
|
||||||
|
#define STR(a) _STR(a)
|
||||||
|
|
||||||
|
#define bug(...) do { fprintf(stderr,"["__FILE__":"STR(__LINE__)"]ERROR: "__VA_ARGS__); exit(1); } while(0)
|
||||||
|
#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0)
|
||||||
|
|
||||||
|
extern bool g_debug;
|
||||||
|
|
||||||
|
typedef struct crypto_key_t *key_array_t;
|
||||||
|
int g_nr_keys;
|
||||||
|
key_array_t g_key_array;
|
||||||
|
|
||||||
|
char *s_getenv(const char *name);
|
||||||
|
void generate_random_data(void *buf, size_t sz);
|
||||||
|
void *xmalloc(size_t s);
|
||||||
|
int convxdigit(char digit, byte *val);
|
||||||
|
void print_hex(byte *data, int len, bool newline);
|
||||||
|
void add_keys(key_array_t ka, int kac);
|
||||||
|
key_array_t read_keys(const char *key_file, int *num_keys);
|
||||||
|
void print_key(struct crypto_key_t *key, bool newline);
|
||||||
|
|
||||||
|
#endif /* __MISC_H__ */
|
||||||
|
|
@ -28,21 +28,19 @@
|
||||||
|
|
||||||
#define _ISOC99_SOURCE /* snprintf() */
|
#define _ISOC99_SOURCE /* snprintf() */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "sb.h"
|
#include "sb.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
#if 1 /* ANSI colors */
|
#if 1 /* ANSI colors */
|
||||||
|
|
||||||
|
|
@ -60,104 +58,24 @@ char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
|
||||||
# define color(a)
|
# define color(a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0)
|
|
||||||
#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0)
|
|
||||||
|
|
||||||
/* all blocks are sized as a multiple of 0x1ff */
|
/* all blocks are sized as a multiple of 0x1ff */
|
||||||
#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
|
#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
|
||||||
|
|
||||||
/* If you find a firmware that breaks the known format ^^ */
|
/* If you find a firmware that breaks the known format ^^ */
|
||||||
#define assert(a) do { if(!(a)) { fprintf(stderr,"Assertion \"%s\" failed in %s() line %d!\n\nPlease send us your firmware!\n",#a,__func__,__LINE__); exit(1); } } while(0)
|
#define assert(a) do { if(!(a)) { fprintf(stderr,"Assertion \"%s\" failed in %s() line %d!\n\nPlease send us your firmware!\n",#a,__func__,__LINE__); exit(1); } } while(0)
|
||||||
|
|
||||||
|
#define crypto_cbc(...) \
|
||||||
|
do { int ret = crypto_cbc(__VA_ARGS__); \
|
||||||
|
if(ret != CRYPTO_ERROR_SUCCESS) \
|
||||||
|
bug("crypto_cbc error: %d\n", ret); \
|
||||||
|
}while(0)
|
||||||
|
|
||||||
/* globals */
|
/* globals */
|
||||||
|
|
||||||
uint8_t *g_buf; /* file content */
|
uint8_t *g_buf; /* file content */
|
||||||
#define PREFIX_SIZE 128
|
char *g_out_prefix;
|
||||||
char out_prefix[PREFIX_SIZE];
|
bool g_debug;
|
||||||
const char *key_file;
|
bool g_raw_mode;
|
||||||
|
|
||||||
char *s_getenv(const char *name)
|
|
||||||
{
|
|
||||||
char *s = getenv(name);
|
|
||||||
return s ? s : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void *xmalloc(size_t s) /* malloc helper, used in elf.c */
|
|
||||||
{
|
|
||||||
void * r = malloc(s);
|
|
||||||
if(!r) bugp("malloc");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_hex(byte *data, int len, bool newline)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < len; i++)
|
|
||||||
printf("%02X ", data[i]);
|
|
||||||
if(newline)
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int convxdigit(char digit, byte *val)
|
|
||||||
{
|
|
||||||
if(digit >= '0' && digit <= '9')
|
|
||||||
{
|
|
||||||
*val = digit - '0';
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if(digit >= 'A' && digit <= 'F')
|
|
||||||
{
|
|
||||||
*val = digit - 'A' + 10;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if(digit >= 'a' && digit <= 'f')
|
|
||||||
{
|
|
||||||
*val = digit - 'a' + 10;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef byte (*key_array_t)[16];
|
|
||||||
|
|
||||||
static key_array_t read_keys(int num_keys)
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
struct stat st;
|
|
||||||
int fd = open(key_file,O_RDONLY);
|
|
||||||
if(fd == -1)
|
|
||||||
bugp("opening key file failed");
|
|
||||||
if(fstat(fd,&st) == -1)
|
|
||||||
bugp("key file stat() failed");
|
|
||||||
size = st.st_size;
|
|
||||||
char *buf = xmalloc(size);
|
|
||||||
if(read(fd, buf, size) != (ssize_t)size)
|
|
||||||
bugp("reading key file");
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
key_array_t keys = xmalloc(sizeof(byte[16]) * num_keys);
|
|
||||||
int pos = 0;
|
|
||||||
for(int i = 0; i < num_keys; i++)
|
|
||||||
{
|
|
||||||
/* skip ws */
|
|
||||||
while(pos < size && isspace(buf[pos]))
|
|
||||||
pos++;
|
|
||||||
/* enough space ? */
|
|
||||||
if((pos + 32) > size)
|
|
||||||
bugp("invalid key file (not enough keys)");
|
|
||||||
for(int j = 0; j < 16; j++)
|
|
||||||
{
|
|
||||||
byte a, b;
|
|
||||||
if(convxdigit(buf[pos + 2 * j], &a) || convxdigit(buf[pos + 2 * j + 1], &b))
|
|
||||||
bugp(" invalid key, it should be a 128-bit key written in hexadecimal\n");
|
|
||||||
keys[i][j] = (a << 4) | b;
|
|
||||||
}
|
|
||||||
pos += 32;
|
|
||||||
}
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
|
#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
|
||||||
|
|
||||||
|
|
@ -195,17 +113,21 @@ static void extract_elf_section(struct elf_params_t *elf, int count, const char
|
||||||
|
|
||||||
static void extract_section(int data_sec, char name[5], byte *buf, int size, const char *indent)
|
static void extract_section(int data_sec, char name[5], byte *buf, int size, const char *indent)
|
||||||
{
|
{
|
||||||
char filename[PREFIX_SIZE + 32];
|
char *filename = xmalloc(strlen(g_out_prefix) + strlen(name) + 5);
|
||||||
snprintf(filename, sizeof filename, "%s%s.bin", out_prefix, name);
|
if(g_out_prefix)
|
||||||
FILE *fd = fopen(filename, "wb");
|
{
|
||||||
if (fd != NULL) {
|
sprintf(filename, "%s%s.bin", g_out_prefix, name);
|
||||||
fwrite(buf, size, 1, fd);
|
FILE *fd = fopen(filename, "wb");
|
||||||
fclose(fd);
|
if (fd != NULL)
|
||||||
|
{
|
||||||
|
fwrite(buf, size, 1, fd);
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(data_sec)
|
if(data_sec)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
snprintf(filename, sizeof filename, "%s%s", out_prefix, name);
|
sprintf(filename, "%s%s", g_out_prefix, name);
|
||||||
|
|
||||||
/* elf construction */
|
/* elf construction */
|
||||||
struct elf_params_t elf;
|
struct elf_params_t elf;
|
||||||
|
|
@ -484,19 +406,23 @@ static void extract(unsigned long filesize)
|
||||||
printf("0x%08x\n", sb_header->first_boot_sec_id);
|
printf("0x%08x\n", sb_header->first_boot_sec_id);
|
||||||
|
|
||||||
/* encryption cbc-mac */
|
/* encryption cbc-mac */
|
||||||
key_array_t keys = NULL; /* array of 16-bytes keys */
|
|
||||||
byte real_key[16];
|
byte real_key[16];
|
||||||
bool valid_key = false; /* false until a matching key was found */
|
bool valid_key = false; /* false until a matching key was found */
|
||||||
if(sb_header->nr_keys > 0)
|
if(sb_header->nr_keys > 0)
|
||||||
{
|
{
|
||||||
keys = read_keys(sb_header->nr_keys);
|
if(sb_header->nr_keys > g_nr_keys)
|
||||||
|
{
|
||||||
|
color(GREY);
|
||||||
|
bug("SB file has %d keys but only %d were specified on command line\n",
|
||||||
|
sb_header->nr_keys, g_nr_keys);
|
||||||
|
}
|
||||||
color(BLUE);
|
color(BLUE);
|
||||||
printf("Encryption data\n");
|
printf("Encryption data\n");
|
||||||
for(int i = 0; i < sb_header->nr_keys; i++)
|
for(int i = 0; i < sb_header->nr_keys; i++)
|
||||||
{
|
{
|
||||||
color(RED);
|
color(RED);
|
||||||
printf(" Key %d: ", i);
|
printf(" Key %d: ", i);
|
||||||
print_hex(keys[i], 16, true);
|
print_key(&g_key_array[i], true);
|
||||||
color(GREEN);
|
color(GREEN);
|
||||||
printf(" CBC-MAC of headers: ");
|
printf(" CBC-MAC of headers: ");
|
||||||
|
|
||||||
|
|
@ -512,8 +438,8 @@ static void extract(unsigned long filesize)
|
||||||
byte computed_cbc_mac[16];
|
byte computed_cbc_mac[16];
|
||||||
byte zero[16];
|
byte zero[16];
|
||||||
memset(zero, 0, 16);
|
memset(zero, 0, 16);
|
||||||
cbc_mac(g_buf, NULL, sb_header->header_size + sb_header->nr_sections,
|
crypto_cbc(g_buf, NULL, sb_header->header_size + sb_header->nr_sections,
|
||||||
keys[i], zero, &computed_cbc_mac, 1);
|
&g_key_array[i], zero, &computed_cbc_mac, 1);
|
||||||
color(RED);
|
color(RED);
|
||||||
bool ok = memcmp(dict_entry->hdr_cbc_mac, computed_cbc_mac, 16) == 0;
|
bool ok = memcmp(dict_entry->hdr_cbc_mac, computed_cbc_mac, 16) == 0;
|
||||||
if(ok)
|
if(ok)
|
||||||
|
|
@ -533,7 +459,7 @@ static void extract(unsigned long filesize)
|
||||||
byte decrypted_key[16];
|
byte decrypted_key[16];
|
||||||
byte iv[16];
|
byte iv[16];
|
||||||
memcpy(iv, g_buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
|
memcpy(iv, g_buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
|
||||||
cbc_mac(dict_entry->key, decrypted_key, 1, keys[i], iv, NULL, 0);
|
crypto_cbc(dict_entry->key, decrypted_key, 1, &g_key_array[i], iv, NULL, 0);
|
||||||
printf(" Decrypted key : ");
|
printf(" Decrypted key : ");
|
||||||
color(YELLOW);
|
color(YELLOW);
|
||||||
print_hex(decrypted_key, 16, false);
|
print_hex(decrypted_key, 16, false);
|
||||||
|
|
@ -769,37 +695,127 @@ static void extract(unsigned long filesize)
|
||||||
printf(" Failed\n");
|
printf(" Failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
void usage(void)
|
||||||
{
|
{
|
||||||
int fd;
|
printf("Usage: sbtoelf [options] sb-file\n");
|
||||||
struct stat st;
|
printf("Options:\n");
|
||||||
if(argc != 3 && argc != 4)
|
printf(" -?/--help\tDisplay this message\n");
|
||||||
|
printf(" -o <file>\tSet output prefix\n");
|
||||||
|
printf(" -d/--debug\tEnable debug output\n");
|
||||||
|
printf(" -k <file>\tAdd key file\n");
|
||||||
|
printf(" -z\t\tAdd zero key\n");
|
||||||
|
printf(" -r\t\tUse raw command mode\n");
|
||||||
|
printf(" --single-key <key>\tAdd single key\n");
|
||||||
|
printf(" --usb-otp <vid>:<pid>\tAdd USB OTP device\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct crypto_key_t g_zero_key =
|
||||||
|
{
|
||||||
|
.method = CRYPTO_KEY,
|
||||||
|
.u.key = {0}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
while(1)
|
||||||
{
|
{
|
||||||
printf("Usage: %s <firmware> <key file> [<out prefix>]\n",*argv);
|
static struct option long_options[] =
|
||||||
printf("To use raw command mode, set environment variable SB_RAW_CMD to YES\n");
|
{
|
||||||
return 1;
|
{"help", no_argument, 0, '?'},
|
||||||
|
{"debug", no_argument, 0, 'd'},
|
||||||
|
{"single-key", required_argument, 0, 's'},
|
||||||
|
{"usb-otp", required_argument, 0, 'u'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
int c = getopt_long(argc, argv, "?do:k:zr", long_options, NULL);
|
||||||
|
if(c == -1)
|
||||||
|
break;
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
g_debug = true;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
g_out_prefix = optarg;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
{
|
||||||
|
int kac;
|
||||||
|
key_array_t ka = read_keys(optarg, &kac);
|
||||||
|
add_keys(ka, kac);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'z':
|
||||||
|
{
|
||||||
|
add_keys(&g_zero_key, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
{
|
||||||
|
struct crypto_key_t key;
|
||||||
|
key.method = CRYPTO_KEY;
|
||||||
|
if(strlen(optarg) != 32)
|
||||||
|
bug("The key given in argument is invalid");
|
||||||
|
for(int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
byte a, b;
|
||||||
|
if(convxdigit(optarg[2 * i], &a) || convxdigit(optarg[2 * i + 1], &b))
|
||||||
|
bugp("The key given in argument is invalid\n");
|
||||||
|
key.u.key[i] = (a << 4) | b;
|
||||||
|
}
|
||||||
|
add_keys(&key, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u':
|
||||||
|
{
|
||||||
|
int vid, pid;
|
||||||
|
char *p = strchr(optarg, ':');
|
||||||
|
if(p == NULL)
|
||||||
|
bug("Invalid VID/PID\n");
|
||||||
|
|
||||||
|
char *end;
|
||||||
|
vid = strtol(optarg, &end, 16);
|
||||||
|
if(end != p)
|
||||||
|
bug("Invalid VID/PID\n");
|
||||||
|
pid = strtol(p + 1, &end, 16);
|
||||||
|
if(end != (optarg + strlen(optarg)))
|
||||||
|
bug("Invalid VID/PID\n");
|
||||||
|
struct crypto_key_t key;
|
||||||
|
key.method = CRYPTO_USBOTP;
|
||||||
|
key.u.vid_pid = vid << 16 | pid;
|
||||||
|
add_keys(&key, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(argc == 4)
|
if(argc - optind != 1)
|
||||||
snprintf(out_prefix, PREFIX_SIZE, "%s", argv[3]);
|
bug("Missing sb file or too many files after options\n");
|
||||||
else
|
|
||||||
strcpy(out_prefix, "");
|
|
||||||
|
|
||||||
if( (fd = open(argv[1], O_RDONLY)) == -1 )
|
const char *sb_file = argv[optind];
|
||||||
bugp("opening firmware failed");
|
FILE *fd = fopen(sb_file, "rb");
|
||||||
|
if(fd == NULL)
|
||||||
|
bug("Cannot open input file\n");
|
||||||
|
fseek(fd, 0, SEEK_END);
|
||||||
|
size_t size = ftell(fd);
|
||||||
|
fseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
key_file = argv[2];
|
g_buf = xmalloc(size);
|
||||||
|
if(fread(g_buf, 1, size, fd) != size) /* load the whole file into memory */
|
||||||
if(fstat(fd, &st) == -1)
|
|
||||||
bugp("firmware stat() failed");
|
|
||||||
|
|
||||||
g_buf = xmalloc(st.st_size);
|
|
||||||
if(read(fd, g_buf, st.st_size) != (ssize_t)st.st_size) /* load the whole file into memory */
|
|
||||||
bugp("reading firmware");
|
bugp("reading firmware");
|
||||||
|
|
||||||
close(fd);
|
fclose(fd);
|
||||||
|
|
||||||
extract(st.st_size);
|
extract(size);
|
||||||
|
|
||||||
color(OFF);
|
color(OFF);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue