/* * Copyright (c) 2014, Lars Schmertmann . * 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 #include #include #include #include #include #include #include #include #include #include #include #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 [ ...]\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 = ";rt=\"dev.info\";if=\"core.rp\"," ";rt=\"dev.info\";if=\"core.rp\"," ";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); } } }