mirror of https://github.com/rusefi/hex2dfu.git
new version 1.1
Code signing added using ED25519 algorithm.
This commit is contained in:
parent
744acf4156
commit
56a97615e2
|
@ -18,6 +18,10 @@ I`m using mingw32 under Windows, change parameters regards your enviroment.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
To enable ED25519 code signing feature, download ED25519 code from https://github.com/encedo/ed25519 or https://github.com/orlp/ed25519 to folder ED25519
|
||||||
|
and type:
|
||||||
|
|
||||||
|
gcc hex2dfu.c ED25519/*.c -o hex2dfu.exe
|
||||||
|
|
||||||
|
|
||||||
Using
|
Using
|
||||||
|
@ -43,8 +47,11 @@ Using
|
||||||
hex2dfu.exe -i infile.hex -o outfile.dfu -c 0x08011000
|
hex2dfu.exe -i infile.hex -o outfile.dfu -c 0x08011000
|
||||||
|
|
||||||
|
|
||||||
|
4. Code siging: To sign the code ED25519 'secret' need to be provided
|
||||||
|
|
||||||
|
hex2dfu.exe -i infile.hex -o outfile.dfu -c 0x08011000 -S d4411fa9d5cb6f91b7bd18e4ab41e7d03bf37e1d738c12b923ef0f09de90e6cf
|
||||||
|
|
||||||
|
|
||||||
Automated CRC32 generation in very usefull when custom bootloader is in use. We can check firmware at every MCU boot and execute only when file ingerrity is authenticated. Otherwise performe failover (e.g. start USB bootloader).
|
Automated CRC32 generation in very usefull when custom bootloader is in use. We can check firmware at every MCU boot and execute only when file ingerrity is authenticated. Otherwise performe failover (e.g. start USB bootloader).
|
||||||
|
|
||||||
Custom USB Bootloader supporting CRC32 checking during boot will be open sourced soon. Stay tuned :)
|
Custom USB Bootloader supporting CRC32 checking during boot will be open sourced soon. Stay tuned :)
|
||||||
|
|
92
hex2dfu.c
92
hex2dfu.c
|
@ -4,19 +4,42 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define TARGET_NAME_ENCEDO "Encedo"
|
#define TARGET_NAME_ENCEDO "EncedoKey"
|
||||||
|
// uncomment to add support for digital code signature using ED25519
|
||||||
|
#define ED25519_SUPPORT
|
||||||
|
|
||||||
|
#ifdef ED25519_SUPPORT
|
||||||
|
#include "ED25519/sha512.h"
|
||||||
|
#include "ED25519/ed25519.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
To build:
|
||||||
|
1. download ED25519 code from https://github.com/encedo/ed25519 or https://github.com/orlp/ed25519 to folder ED25519
|
||||||
|
2. compile gcc hex2dfu.c ED25519/*.c -o hex2dfu.exe
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void print_help(void);
|
void print_help(void);
|
||||||
int hex2bin(unsigned char *obuf, const char *ibuf, int len);
|
int hex2bin(unsigned char *obuf, const char *ibuf, int len);
|
||||||
int check_checksum(unsigned char *inbuf, int len);
|
int check_checksum(unsigned char *inbuf, int len);
|
||||||
unsigned char *ihex2bin_buf(unsigned int *start_address, int *dst_len, FILE *inFile);
|
unsigned char *ihex2bin_buf(unsigned int *start_address, int *dst_len, FILE *inFile);
|
||||||
|
|
||||||
uint32_t crc32(uint32_t crc, const void *buf, size_t size);
|
uint32_t crc32(uint32_t crc, const void *buf, size_t size);
|
||||||
|
|
||||||
|
//efab5b0739a834bac702aeb5cd08ffe227908faaae501f910e7e07d8d41fbb06
|
||||||
int main (int argc, char **argv) {
|
int main (int argc, char **argv) {
|
||||||
int i, c, vid =0x0483, pid = 0xdf11, ver = 0xffff;
|
int i, c, vid =0x0483, pid = 0xdf11, ver = 0xffff;
|
||||||
char *tar0 = NULL, *tar0_lab = NULL, *out_fn = NULL;
|
char *tar0 = NULL, *tar0_lab = NULL, *out_fn = NULL;
|
||||||
FILE *inFile, *outFile;
|
FILE *inFile, *outFile;
|
||||||
|
|
||||||
|
#ifdef ED25519_SUPPORT
|
||||||
|
unsigned char hash_buf[64];
|
||||||
|
sha512_context hash;
|
||||||
|
unsigned char *ed25519_secret = NULL;
|
||||||
|
unsigned char public_key[32], private_key[64], signature[64];
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned int tar0_start_address;
|
unsigned int tar0_start_address;
|
||||||
int tar0_len;
|
int tar0_len;
|
||||||
|
@ -27,7 +50,7 @@ int main (int argc, char **argv) {
|
||||||
unsigned int crc = 0, tmp, add_crc32 = 0;
|
unsigned int crc = 0, tmp, add_crc32 = 0;
|
||||||
|
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
while ((c = getopt (argc, argv, "hv:p:d:i:l:o:c:")) != -1) {
|
while ((c = getopt (argc, argv, "hv:p:d:i:l:o:c:S:")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'i': //target0 input file name
|
case 'i': //target0 input file name
|
||||||
tar0 = optarg;
|
tar0 = optarg;
|
||||||
|
@ -47,6 +70,14 @@ int main (int argc, char **argv) {
|
||||||
case 'c': //place crc32 at this address
|
case 'c': //place crc32 at this address
|
||||||
add_crc32 = strtol (optarg, NULL, 16);
|
add_crc32 = strtol (optarg, NULL, 16);
|
||||||
break;
|
break;
|
||||||
|
case 'S': //ED25519 secret, hex
|
||||||
|
#ifndef ED25519_SUPPORT
|
||||||
|
fprintf (stderr, "Code signing not supported!\n");
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
ed25519_secret = optarg;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
case 'o': //output file name
|
case 'o': //output file name
|
||||||
out_fn = optarg;
|
out_fn = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -70,19 +101,60 @@ int main (int argc, char **argv) {
|
||||||
perror ("No output file specifed.\n");
|
perror ("No output file specifed.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ED25519_SUPPORT
|
||||||
|
if (ed25519_secret) {
|
||||||
|
c = hex2bin(ed25519_secret, ed25519_secret, strlen(ed25519_secret));
|
||||||
|
if (c != 32) {
|
||||||
|
perror ("ED25519 'secret' have to be 32bytes long.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ed25519_create_keypair(public_key, private_key, ed25519_secret);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
inFile = fopen ( tar0, "r");
|
inFile = fopen ( tar0, "r");
|
||||||
tar0_buf = ihex2bin_buf(&tar0_start_address, &tar0_len, inFile);
|
tar0_buf = ihex2bin_buf(&tar0_start_address, &tar0_len, inFile);
|
||||||
|
|
||||||
fclose (inFile);
|
fclose (inFile);
|
||||||
if (tar0_buf && (tar0_len > 0)) {
|
if (tar0_buf && (tar0_len > 0)) {
|
||||||
printf("Data Start Address: 0x%08x\r\n", tar0_start_address);
|
printf("Data Start Address: 0x%08x\r\n", tar0_start_address);
|
||||||
printf("Data Length: %ub\r\n", tar0_len);
|
printf("Data Length: %ub\r\n", tar0_len);
|
||||||
if ((add_crc32>0) && (add_crc32 < (tar0_start_address+tar0_len-4))) { //-c request CRC32 placement at given address
|
if ((add_crc32>0) && (add_crc32 < (tar0_start_address+tar0_len-256))) { //-c request CRC32 placement at given address
|
||||||
add_crc32 -= tar0_start_address;
|
add_crc32 -= tar0_start_address;
|
||||||
tar0_buf[add_crc32 + 4] = tar0_len>>0 & 0xFF; //binary code length first(little endian)
|
tar0_buf[add_crc32 + 4] = tar0_len>>0 & 0xFF; //binary code length first(little endian)
|
||||||
tar0_buf[add_crc32 + 5] = tar0_len>>8 & 0xFF;
|
tar0_buf[add_crc32 + 5] = tar0_len>>8 & 0xFF;
|
||||||
tar0_buf[add_crc32 + 6] = tar0_len>>16 & 0xFF;
|
tar0_buf[add_crc32 + 6] = tar0_len>>16 & 0xFF;
|
||||||
tar0_buf[add_crc32 + 7] = tar0_len>>24 & 0xFF;
|
tar0_buf[add_crc32 + 7] = tar0_len>>24 & 0xFF;
|
||||||
|
#ifdef ED25519_SUPPORT
|
||||||
|
if (ed25519_secret) {
|
||||||
|
sha512_init(&hash);
|
||||||
|
sha512_update(&hash, tar0_buf, add_crc32);
|
||||||
|
sha512_update(&hash, tar0_buf+add_crc32+256, tar0_len-(add_crc32+256));
|
||||||
|
sha512_final(&hash, hash_buf);
|
||||||
|
printf("SHA512: ");
|
||||||
|
for(c=0; c<64; c++) {
|
||||||
|
printf("%02x", (unsigned char)hash_buf[c]);
|
||||||
|
}
|
||||||
|
printf("\r\n");
|
||||||
|
|
||||||
|
ed25519_sign(signature, hash_buf, 64, public_key, private_key);
|
||||||
|
memmove(tar0_buf+add_crc32+0x10, signature, 64);
|
||||||
|
memmove(tar0_buf+add_crc32+0x10+64, public_key, 32);
|
||||||
|
|
||||||
|
printf("ED25519 PublicKey: ");
|
||||||
|
for(c=0; c<32; c++) {
|
||||||
|
printf("%02x", (unsigned char)public_key[c]);
|
||||||
|
}
|
||||||
|
printf("\r\n");
|
||||||
|
|
||||||
|
printf("ED25519 Signature: ");
|
||||||
|
for(c=0; c<64; c++) {
|
||||||
|
printf("%02x", (unsigned char)signature[c]);
|
||||||
|
}
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
crc = crc32(0, tar0_buf, add_crc32); //calc CRC upto placement address
|
crc = crc32(0, tar0_buf, add_crc32); //calc CRC upto placement address
|
||||||
crc = crc32(crc, tar0_buf+add_crc32+4, tar0_len-(add_crc32+4)); //calc the rest of - starting from placement+4 up to end
|
crc = crc32(crc, tar0_buf+add_crc32+4, tar0_len-(add_crc32+4)); //calc the rest of - starting from placement+4 up to end
|
||||||
tar0_buf[add_crc32] = crc>>0 & 0xFF; //CRC placement (little endian)
|
tar0_buf[add_crc32] = crc>>0 & 0xFF; //CRC placement (little endian)
|
||||||
|
@ -91,7 +163,7 @@ int main (int argc, char **argv) {
|
||||||
tar0_buf[add_crc32 + 3] = crc>>24 & 0xFF;
|
tar0_buf[add_crc32 + 3] = crc>>24 & 0xFF;
|
||||||
printf("Additional CRC32 data: 0x%08x:0x%08x\r\n",add_crc32+tar0_start_address ,crc);
|
printf("Additional CRC32 data: 0x%08x:0x%08x\r\n",add_crc32+tar0_start_address ,crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
dfu_len = 11 + 274 + 8+ tar0_len + 16;
|
dfu_len = 11 + 274 + 8+ tar0_len + 16;
|
||||||
dfu = calloc(1, dfu_len);
|
dfu = calloc(1, dfu_len);
|
||||||
if (dfu) {
|
if (dfu) {
|
||||||
|
@ -176,8 +248,8 @@ int main (int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_help(void) {
|
void print_help(void) {
|
||||||
printf("STM32 hex2dfu version 1.0\r\n");
|
printf("STM32 hex2dfu version 1.1\r\n");
|
||||||
printf("(c) Encedo Ltd 2013-2014\r\n");
|
printf("(c) Encedo Ltd 2013-2015\r\n");
|
||||||
printf("Options:\r\n");
|
printf("Options:\r\n");
|
||||||
printf("-c - place CRC23 under this addres (optional)\r\n");
|
printf("-c - place CRC23 under this addres (optional)\r\n");
|
||||||
printf("-d - file version number (optional, default: 0xFFFF)\r\n");
|
printf("-d - file version number (optional, default: 0xFFFF)\r\n");
|
||||||
|
@ -185,6 +257,7 @@ void print_help(void) {
|
||||||
printf("-i - Target0 HEX file name (mandatory)\r\n");
|
printf("-i - Target0 HEX file name (mandatory)\r\n");
|
||||||
printf("-l - Target0 name (optional, default: EncedoKey)\r\n");
|
printf("-l - Target0 name (optional, default: EncedoKey)\r\n");
|
||||||
printf("-o - output DFU file name (mandatory)\r\n");
|
printf("-o - output DFU file name (mandatory)\r\n");
|
||||||
|
printf("-S - ED25519 'secret' to sign the code (optional)\r\n");
|
||||||
printf("-p - USB Pid (optional, default: 0xDF11)\r\n");
|
printf("-p - USB Pid (optional, default: 0xDF11)\r\n");
|
||||||
printf("-v - USB Vid (optional, default: 0x0483)\r\n");
|
printf("-v - USB Vid (optional, default: 0x0483)\r\n");
|
||||||
printf("Example: hex2dfu -i infile.hex -i outfile.dfu\r\n");
|
printf("Example: hex2dfu -i infile.hex -i outfile.dfu\r\n");
|
||||||
|
@ -256,11 +329,11 @@ unsigned char *ihex2bin_buf(unsigned int *start_address, int *dst_len, FILE *inF
|
||||||
return dst;
|
return dst;
|
||||||
} else
|
} else
|
||||||
if (raw[3] == 0) { //>Data record - process
|
if (raw[3] == 0) { //>Data record - process
|
||||||
|
pos = elar + ( (unsigned int)raw[1]<<8 | (unsigned int)raw[2] ); //get start address of this chunk
|
||||||
if (start_set==0) {
|
if (start_set==0) {
|
||||||
*start_address = elar; //set it as new start addres - only possible for first data record
|
*start_address = pos; //set it as new start addres - only possible for first data record
|
||||||
start_set = 1; //only once - this is start address of thye binary data
|
start_set = 1; //only once - this is start address of thye binary data
|
||||||
}
|
}
|
||||||
pos = elar + ( (unsigned int)raw[1]<<8 | (unsigned int)raw[2] ); //get start address of this chunk
|
|
||||||
pos -= *start_address;
|
pos -= *start_address;
|
||||||
cnt = raw[0]; //get chunk size/length
|
cnt = raw[0]; //get chunk size/length
|
||||||
if (pos+cnt > *dst_len) { //enlarge buffer if required
|
if (pos+cnt > *dst_len) { //enlarge buffer if required
|
||||||
|
@ -389,3 +462,4 @@ unsigned int crc32(unsigned int crc, const void *buf, size_t size) {
|
||||||
return crc ^ ~0U;
|
return crc ^ ~0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue