331 lines
11 KiB
C
331 lines
11 KiB
C
/*
|
|
* Copyright (c) 2014, Lars Schmertmann <SmallLars@t-online.de>.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* This file is part of the Contiki operating system.
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <uuid/uuid.h>
|
|
#include <libconfig.h>
|
|
#include <time.h>
|
|
#include <qrencode.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include "blaster.h"
|
|
|
|
char *anschars = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
|
|
|
|
/* ---------------------------------------------------------------------------- */
|
|
|
|
FILE *openFile(const char *name, const char *appendix, const char *mode);
|
|
void writeStandardConfig();
|
|
void writeImg(FILE *file, unsigned char *data, int width);
|
|
|
|
/* ---------------------------------------------------------------------------- */
|
|
|
|
int
|
|
main(int nArgs, char **argv)
|
|
{
|
|
unsigned int c, i, config;
|
|
unsigned int buf[64];
|
|
|
|
if(nArgs < 2) {
|
|
writeStandardConfig();
|
|
|
|
fprintf(stderr, "Missing parameter: ./blaster <config.cfg> [<config.cfg> <config.cfg> ...]\n");
|
|
fprintf(stderr, "Configuration template was created ib config.cfg.\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* qrdata = "UUID:PSK\0" */
|
|
char qrdata[54];
|
|
qrdata[36] = ':';
|
|
qrdata[53] = '\0';
|
|
|
|
config_t cfg;
|
|
for(config = 1; config < nArgs; config++) {
|
|
config_init(&cfg);
|
|
config_setting_t *setting;
|
|
const char *str_val;
|
|
if(access(argv[config], F_OK) == 0) {
|
|
config_read_file(&cfg, argv[config]);
|
|
} else {
|
|
fprintf(stderr, "Unable to read config file.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
fprintf(stdout, "Working on %s ... ", argv[config]);
|
|
|
|
config_lookup_string(&cfg, "input", &str_val);
|
|
FILE *in_bin = openFile(str_val, ".bin", "r");
|
|
|
|
config_lookup_string(&cfg, "output", &str_val);
|
|
FILE *out_bin = openFile(str_val, ".bin", "w");
|
|
FILE *out_txt = openFile(str_val, ".txt", "w");
|
|
FILE *out_pbm = openFile(str_val, ".pbm", "w");
|
|
|
|
char output[131072];
|
|
for(i = 8; (c = fgetc(in_bin)) != EOF; i++) {
|
|
output[i] = (unsigned char)c;
|
|
}
|
|
/* Set original length of firmware in little endian format ------------------- */
|
|
unsigned int length = i - 8;
|
|
memcpy(output + 4, (const void *)&length, 4);
|
|
fprintf(out_txt, "Length: %u = 0x%08x\n", length, length);
|
|
|
|
/* Fill additional flash with zeros for initialisation */
|
|
for(; i < 0x1F000; i++) {
|
|
output[i] = 0x00;
|
|
}
|
|
|
|
/* Example: Write an CoRE-Link-Answer for CoAP -------------------------------- */
|
|
char *buffer = "</d/name>;rt=\"dev.info\";if=\"core.rp\","
|
|
"</d/model>;rt=\"dev.info\";if=\"core.rp\","
|
|
"</d/uuid>;rt=\"dev.info\";if=\"core.rp\"";
|
|
memcpy(output + RES_D_CORE, buffer, LEN_D_CORE);
|
|
|
|
/* Contiki configuration ------------------------------------------------------ */
|
|
output[RES_CONFIG + 0] = 0x22;
|
|
output[RES_CONFIG + 1] = 0x13;
|
|
output[RES_CONFIG + 2] = 1;
|
|
output[RES_CONFIG + 3] = 0;
|
|
|
|
setting = config_lookup(&cfg, "eui");
|
|
for(i = 0; i < 8; i++) {
|
|
output[RES_CONFIG + 8 + i] = config_setting_get_int_elem(setting, 7 - i);
|
|
}
|
|
fprintf(out_txt,
|
|
"EUI: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n",
|
|
(uint8_t)output[RES_CONFIG + 15],
|
|
(uint8_t)output[RES_CONFIG + 14],
|
|
(uint8_t)output[RES_CONFIG + 13],
|
|
(uint8_t)output[RES_CONFIG + 12],
|
|
(uint8_t)output[RES_CONFIG + 11],
|
|
(uint8_t)output[RES_CONFIG + 10],
|
|
(uint8_t)output[RES_CONFIG + 9],
|
|
(uint8_t)output[RES_CONFIG + 8]
|
|
);
|
|
|
|
output[RES_CONFIG + 16] = 15;
|
|
output[RES_CONFIG + 17] = 17;
|
|
output[RES_CONFIG + 18] = 0;
|
|
output[RES_CONFIG + 19] = 0;
|
|
output[RES_CONFIG + 20] = 5;
|
|
output[RES_CONFIG + 21] = 0;
|
|
output[RES_CONFIG + 22] = 0;
|
|
output[RES_CONFIG + 23] = 0;
|
|
|
|
/* Example: Set UUID ---------------------------------------------------------- */
|
|
config_lookup_string(&cfg, "uuid", &str_val);
|
|
memcpy(qrdata, str_val, 36);
|
|
unsigned char uuid_bin[16];
|
|
uuid_parse(str_val, uuid_bin);
|
|
for(i = 0; i < 16; i++) {
|
|
output[RES_UUID + i] = uuid_bin[i];
|
|
}
|
|
fprintf(out_txt, "UUID: %s\n", str_val);
|
|
|
|
/* Example: Set PSK ----------------------------------------------------------- */
|
|
config_lookup_string(&cfg, "psk", &str_val);
|
|
memcpy(qrdata + 37, str_val, 16);
|
|
for(i = 0; i < 16; i++) {
|
|
output[RES_PSK + i] = str_val[i];
|
|
}
|
|
fprintf(out_txt, "PSK: %.*s\n", 16, str_val);
|
|
memcpy(output + RES_ANSCHARS, anschars, LEN_ANSCHARS);
|
|
|
|
/* Example: ECC base point and order for secp256r1 ---------------------------- */
|
|
uint32_t *base_x = (uint32_t *)(output + RES_ECC_BASE_X);
|
|
base_x[0] = 0xd898c296;
|
|
base_x[1] = 0xf4a13945;
|
|
base_x[2] = 0x2deb33a0;
|
|
base_x[3] = 0x77037d81;
|
|
base_x[4] = 0x63a440f2;
|
|
base_x[5] = 0xf8bce6e5;
|
|
base_x[6] = 0xe12c4247;
|
|
base_x[7] = 0x6b17d1f2;
|
|
|
|
uint32_t *base_y = (uint32_t *)(output + RES_ECC_BASE_Y);
|
|
base_y[0] = 0x37bf51f5;
|
|
base_y[1] = 0xcbb64068;
|
|
base_y[2] = 0x6b315ece;
|
|
base_y[3] = 0x2bce3357;
|
|
base_y[4] = 0x7c0f9e16;
|
|
base_y[5] = 0x8ee7eb4a;
|
|
base_y[6] = 0xfe1a7f9b;
|
|
base_y[7] = 0x4fe342e2;
|
|
|
|
uint32_t *order = (uint32_t *)(output + RES_ECC_ORDER);
|
|
order[0] = 0xFC632551;
|
|
order[1] = 0xF3B9CAC2;
|
|
order[2] = 0xA7179E84;
|
|
order[3] = 0xBCE6FAAD;
|
|
order[4] = 0xFFFFFFFF;
|
|
order[5] = 0xFFFFFFFF;
|
|
order[6] = 0x00000000;
|
|
order[7] = 0xFFFFFFFF;
|
|
|
|
/* Example: Set name ---------------------------------------------------------- */
|
|
config_lookup_string(&cfg, "name", &str_val);
|
|
snprintf(output + RES_NAME, LEN_NAME, "%s", str_val);
|
|
fprintf(out_txt, "Name: %s\n", str_val);
|
|
|
|
/* Example: Set model---------------------------------------------------------- */
|
|
config_lookup_string(&cfg, "model", &str_val);
|
|
snprintf(output + RES_MODEL, LEN_MODEL, "%s", str_val);
|
|
fprintf(out_txt, "Model: %s\n", str_val);
|
|
|
|
/* Example: Set time ---------------------------------------------------------- */
|
|
time_t my_time = time(NULL);
|
|
memcpy(output + RES_FLASHTIME, (void *)&my_time, LEN_FLASHTIME);
|
|
struct tm *timeinfo = localtime(&my_time);
|
|
fwrite(buf, 1, strftime((char *)buf, 64, "Created on %d.%m.%Y um %H:%M:%S", timeinfo), out_txt);
|
|
|
|
/* Output result -------------------------------------------------------------- */
|
|
for(i = 4; i < 0x1F000; i++) {
|
|
fputc(output[i], out_bin);
|
|
}
|
|
|
|
/* Generate QR-Code ----------------------------------------------------------- */
|
|
QRcode *code = QRcode_encodeString8bit(qrdata, 3, QR_ECLEVEL_L);
|
|
writeImg(out_pbm, code->data, code->width);
|
|
|
|
fclose(in_bin);
|
|
fclose(out_bin);
|
|
fclose(out_txt);
|
|
fclose(out_pbm);
|
|
|
|
fprintf(stdout, "DONE\n");
|
|
}
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
/* ---------------------------------------------------------------------------- */
|
|
|
|
FILE *
|
|
openFile(const char *name, const char *appendix, const char *mode)
|
|
{
|
|
char filename[64];
|
|
sprintf(filename, "%s%s", name, appendix);
|
|
FILE *file = fopen(filename, mode);
|
|
if(file == NULL) {
|
|
perror("Wasn't able to open file.");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
return file;
|
|
}
|
|
void
|
|
writeStandardConfig()
|
|
{
|
|
unsigned int i;
|
|
|
|
config_t cfg;
|
|
config_init(&cfg);
|
|
config_setting_t *setting;
|
|
|
|
config_setting_t *root = config_root_setting(&cfg);
|
|
|
|
setting = config_setting_add(root, "input", CONFIG_TYPE_STRING);
|
|
config_setting_set_string(setting, "dff_econotag");
|
|
|
|
setting = config_setting_add(root, "output", CONFIG_TYPE_STRING);
|
|
config_setting_set_string(setting, "dff_e_econotag");
|
|
|
|
uint8_t eui[8] = { 0x02, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78 };
|
|
config_setting_t *array = config_setting_add(root, "eui", CONFIG_TYPE_ARRAY);
|
|
for(i = 0; i < 8; ++i) {
|
|
setting = config_setting_add(array, NULL, CONFIG_TYPE_INT);
|
|
config_setting_set_format(setting, CONFIG_FORMAT_HEX);
|
|
config_setting_set_int(setting, eui[i]);
|
|
}
|
|
|
|
unsigned char uuid_bin[16];
|
|
uuid_generate(uuid_bin);
|
|
char uuid[37];
|
|
uuid_unparse(uuid_bin, uuid);
|
|
setting = config_setting_add(root, "uuid", CONFIG_TYPE_STRING);
|
|
config_setting_set_string(setting, uuid);
|
|
|
|
char psk[17];
|
|
psk[16] = '\0';
|
|
FILE *fd = fopen("/dev/urandom", "r");
|
|
if(fd == NULL) {
|
|
perror("Wasn't able to open /dev/urandom: ");
|
|
return;
|
|
}
|
|
for(i = 0; i < 16; i++) {
|
|
int c;
|
|
while((c = fgetc(fd)) == EOF) ;
|
|
psk[i] = anschars[c % 64];
|
|
}
|
|
if(fclose(fd) == -1) {
|
|
perror("Wasn't able to close /dev/urandom: ");
|
|
}
|
|
setting = config_setting_add(root, "psk", CONFIG_TYPE_STRING);
|
|
config_setting_set_string(setting, psk);
|
|
|
|
setting = config_setting_add(root, "name", CONFIG_TYPE_STRING);
|
|
config_setting_set_string(setting, "Blaster Standard Device");
|
|
|
|
setting = config_setting_add(root, "model", CONFIG_TYPE_STRING);
|
|
config_setting_set_string(setting, "Model 1234 for testing purposes only");
|
|
|
|
config_write_file(&cfg, "config.cfg");
|
|
}
|
|
void
|
|
writeImg(FILE *file, unsigned char *data, int width)
|
|
{
|
|
unsigned int buf[width];
|
|
|
|
fprintf(file, "P4\n# %s\n%3u %3u\n", "QR-Code", width * 32, width * 32);
|
|
|
|
int x, y;
|
|
for(y = 0; y < width; y++) {
|
|
for(x = 0; x < width; x++) {
|
|
if(data[(y * width) + x] & 0x01) {
|
|
buf[x] = 0xFFFFFFFF;
|
|
} else {
|
|
buf[x] = 0x00000000;
|
|
}
|
|
}
|
|
for(x = 0; x < 32; x++) {
|
|
fwrite(buf, 4, width, file);
|
|
}
|
|
}
|
|
}
|