aboutsummaryrefslogtreecommitdiff
path: root/source/tools/host/hdr_crypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/tools/host/hdr_crypt.c')
-rw-r--r--source/tools/host/hdr_crypt.c417
1 files changed, 417 insertions, 0 deletions
diff --git a/source/tools/host/hdr_crypt.c b/source/tools/host/hdr_crypt.c
new file mode 100644
index 0000000..2461351
--- /dev/null
+++ b/source/tools/host/hdr_crypt.c
@@ -0,0 +1,417 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "utils.h"
+#include "crypt.h"
+#include "aes.h"
+
+#define MAX_LINE 65535
+
+
+static aes_ctx_t* ctx = NULL;
+static unsigned char aeskey[KEY_256];
+static uint32_t xorkey;
+static unsigned xor_align = 4;
+
+
+char* alignedCopyBuffer(char* orig, unsigned* orig_len, unsigned alignment)
+{
+ unsigned pad = *orig_len % alignment;
+ unsigned new_len = *orig_len + alignment - pad;
+
+ char* out = calloc(new_len, sizeof(char));
+ memcpy(out, orig, *orig_len);
+
+ if (pad > 0)
+ out[*orig_len] = 0;
+ for (unsigned i = (*orig_len)+1; i < new_len; ++i) {
+ out[i] = (char)__rdtsc();
+ }
+ *orig_len = new_len;
+ return out;
+}
+
+enum defType { DT_DEFAULT, DT_SECTION, DT_ENDSECTION };
+struct defines {
+ struct defines* next;
+ enum defType dt;
+ char defName[0];
+};
+static struct defines* defs = NULL;
+
+void addDefineName(const char* line, enum defType type, struct defines** current)
+{
+ if (!current) return;
+
+ const char* strb = strchr(line, ' ');
+ if (!strb) return;
+
+ while (*(++strb) == ' ') {}
+
+ char* stre = strchr(strb, ' ');
+ if (!stre) return;
+
+ size_t len = stre - strb;
+ (*current)->next = calloc(sizeof(struct defines) + len + 1, 1);
+ (*current) = (*current)->next;
+ memcpy( &(*current)->defName[0], &strb[0], len );
+ (*current)->dt = type;
+}
+
+struct entOpts {
+ const char* fmt;
+ const char* com;
+ const char* ent;
+ const char* overw;
+};
+
+void writeOrAbort(const char* outbuf, int outsiz, FILE* outfile)
+{
+ size_t written = fwrite(outbuf, 1, outsiz, outfile);
+ if (written != outsiz) {
+ fprintf(stderr, "Error while writing \"%.*s\" to OUTPUT stream\n", (outsiz > 20 ? 20 : outsiz), outbuf);
+ abort();
+ }
+}
+
+int addStrEntry(FILE* outfile, const char* name, const struct defines* begin, const struct entOpts* opts, bool addSections)
+{
+ const char* name_section = NULL;
+ const struct defines* cur = begin;
+ while ( (cur = cur->next) ) {
+ char* outbuf = NULL;
+ int outsiz = 0;
+
+ /* error checking */
+ if (cur->dt == DT_SECTION && name_section && addSections) {
+ fprintf(stderr, "Found SECTION \"%s\" without ENDSECTION for \"%s\"\n", &cur->defName[0], name_section);
+ return 1;
+ }
+ if (cur->dt == DT_ENDSECTION && !name_section && addSections) {
+ fprintf(stderr, "Found ENDSECTION \"%s\" without ECTION for \"%s\"\n", &cur->defName[0], name_section);
+ return 2;
+ }
+
+ /* prepare output buffer */
+ if ((opts->fmt && cur->dt == DT_SECTION && !name_section) || (!name_section && !addSections)) {
+ /* SECTIONS: generate xor string entries as simple macro */
+
+ if (!addSections) {
+ name_section = "ROOT";
+ const size_t flen = strlen(opts->fmt);
+ const size_t elen = strlen(opts->ent);
+ char* fmt = calloc(flen+elen+1, sizeof(char));
+ strncpy(fmt, opts->fmt, flen);
+ strncpy(fmt+flen, opts->ent, elen);
+ outsiz = asprintf(&outbuf, fmt, opts->com, name, name_section, &cur->defName[0]);
+ free(fmt);
+ } else {
+ name_section = &cur->defName[0];
+ outsiz = asprintf(&outbuf, opts->fmt, opts->com, name, name_section);
+ }
+ } else
+ if (opts->fmt && cur->dt == DT_ENDSECTION && name_section && addSections) {
+ name_section = NULL;
+ fseek(outfile, -4, SEEK_CUR);
+ writeOrAbort(opts->overw, strlen(opts->overw), outfile);
+ } else
+ if (name_section && cur->dt == DT_DEFAULT) {
+ outsiz = asprintf(&outbuf, opts->ent, &cur->defName[0]);
+ }
+ /* ignore section entries if user wants only root section entries */
+ if (!addSections && cur->dt == DT_SECTION) {
+ while ( (cur = cur->next) && cur->dt != DT_ENDSECTION ) {}
+ }
+
+ /* write output buffer */
+ if (outsiz > 0) {
+ writeOrAbort(outbuf, outsiz, outfile);
+ free(outbuf);
+ }
+ }
+ fseek(outfile, -4, SEEK_CUR);
+ writeOrAbort(opts->overw, strlen(opts->overw), outfile);
+
+ return 0;
+}
+
+/* string struct defines for each section */
+static const char fmt_strsec[] = "%s\n#define %s_%s_STRINGS \\\n";
+static const char com_strsec[] = "\n\n/* for use in string struct */";
+static const char fmt_strent[] = " STRENT(%s), \\\n";
+/* replace last 4 bytes with newlines */
+static const char overw[] = "\n\n\n\n";
+
+int addStrStructEntries(FILE* outfile, const char* name, const struct defines* begin, bool addSections)
+{
+ struct entOpts opts = {0};
+ opts.fmt = fmt_strsec;
+ opts.com = com_strsec;
+ opts.ent = fmt_strent;
+ opts.overw = overw;
+ return addStrEntry(outfile, name, begin, &opts, addSections);
+}
+
+/* string enum defines for each section */
+static const char fmt_enmsec[] = "%s\n#define %s_%s_ENUM \\\n";
+static const char com_enmsec[] = "\n\n/* for use in string enum */";
+static const char fmt_enment[] = " %s_ENUM, \\\n";
+
+int addStrEnumEntries(FILE* outfile, const char* name, const struct defines* begin, bool addSections)
+{
+ struct entOpts opts = {0};
+ opts.fmt = fmt_enmsec;
+ opts.com = com_enmsec;
+ opts.ent = fmt_enment;
+ opts.overw = overw;
+ return addStrEntry(outfile, name, begin, &opts, addSections);
+}
+
+char* gencstr(unsigned char* buf, size_t siz)
+{
+ int i;
+ char* buf_str = (char*)calloc(1, 4*siz + 1);
+ char* buf_ptr = buf_str;
+ for (i = 0; i < siz; i++)
+ {
+ buf_ptr += sprintf(buf_ptr, "\\x%02X", buf[i]);
+ }
+ *(buf_ptr) = '\0';
+ return buf_str;
+}
+
+void genUnescapedBuf(char* buf, uint32_t* siz)
+{
+ int i;
+ size_t found = 0;
+ bool hasBackslash = false;
+ for (i = 0; i < *siz; i++)
+ {
+ unsigned char byte = 0x00;
+
+ if (buf[i] == '\\') {
+ if (hasBackslash) {
+ memmove(&buf[i], &buf[i+1], (*siz)-i-1);
+ (*siz)--;
+ buf[(*siz)] = '\0';
+ }
+ hasBackslash = !hasBackslash;
+ continue;
+ }
+
+ if (hasBackslash && buf[i] == 'x') {
+ i++;
+ for (int j = i; j < i+2; j++) {
+ char cur = tolower(buf[j]);
+ unsigned char shifter = (j == i ? 4 : 0);
+ if (cur == '\0') break;
+ if (cur >= 48 && cur <= 57) {
+ byte |= (cur - 48) << shifter;
+ } else if (cur >= 97 && cur <= 102) {
+ byte |= (cur - 97 + 10) << shifter;
+ }
+ }
+ i += 2;
+ buf[i-4] = byte;
+ memmove(buf+i-3, buf+i, (*siz)-i);
+ i -= 4;
+ hasBackslash = false;
+ found++;
+ } else
+ if (hasBackslash)
+ hasBackslash = false;
+ }
+ *siz -= (found*3);
+}
+
+int doSelfTest(void)
+{
+ int ret = 0;
+
+ unsigned char __aeskey[KEY_256+1];
+ memset(&__aeskey[0], '\0', sizeof(unsigned char)*(KEY_256+1));
+ aes_randomkey(&__aeskey[0], KEY_256);
+ aes_ctx_t* __ctx = aes_alloc_ctx(&__aeskey[0], KEY_256);
+
+ char __ptext[16] = "Attack at dawn!";
+ char __ctext[16];
+ char __decptext[16];
+ aes_encrypt(__ctx, (unsigned char*)__ptext, (unsigned char*)__ctext);
+ aes_decrypt(__ctx, (unsigned char*)__ctext, (unsigned char*)__decptext);
+ if (strcmp(__ptext, __decptext) != 0) {
+ ret = 1;
+ goto selftest_fin;
+ }
+
+ char __inbuf[] = "This is a short short short short short text, but bigger than 16 bytes ...";
+ uint32_t __outlen = 0;
+ char* __outbuf = aes_crypt_s(__ctx, __inbuf, sizeof(__inbuf), &__outlen, true);
+ uint32_t __orglen = 0;
+ char* __orgbuf = aes_crypt_s(__ctx, __outbuf, __outlen, &__orglen, false);
+
+ if (strcmp(__inbuf, __orgbuf) != 0)
+ ret = 1;
+
+selftest_fin:
+ free(__orgbuf);
+ free(__outbuf);
+ aes_free_ctx(__ctx);
+ return ret;
+}
+
+int main(int argc, char** argv)
+{
+ aes_init();
+ struct defines* cur = defs = calloc(sizeof(struct defines), 1);
+ int ret = -1;
+ if ( (ret = doSelfTest()) != 0) {
+ printf("%s: SelfTest failed with %d\n", argv[0], ret);
+ }
+
+ if (argc != 5) {
+ printf("usage: %s [AES|XOR] [STRING.h] [CRYPTED.h] [KEYNAME-DEFINE]\n", argv[0]);
+ printf("e.g.: %s aes include/aes_strings.h include/aes_strings_gen.h AESKEY\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ bool doAes;
+ if (strcasecmp(argv[1], "aes") == 0) {
+ doAes = true;
+ } else if (strcasecmp(argv[1], "xor") == 0) {
+ doAes = false;
+ } else {
+ printf("%s error: [AES|XOR] and not %s\n", argv[0], argv[1]);
+ exit(EXIT_FAILURE);
+ }
+
+ char* cstr_key = NULL;
+ if (doAes) {
+ memset(&aeskey[0], '\0', sizeof(aeskey));
+ aes_randomkey(&aeskey[0], sizeof(aeskey));
+
+ ctx = aes_alloc_ctx(&aeskey[0], sizeof(aeskey));
+ cstr_key = gencstr(&aeskey[0], sizeof(aeskey));
+ } else {
+ xorkey = xor32_randomkey();
+ cstr_key = gencstr((unsigned char*)&xorkey, sizeof(xorkey));
+ }
+
+ FILE* infile = fopen(argv[2], "r");
+ FILE* outfile = fopen(argv[3], "w+");
+ if (!infile || !outfile) {
+ printf("%s: %s does not exist!\n", argv[0], (!infile ? argv[2] : argv[3]));
+ exit(EXIT_FAILURE);
+ }
+
+ char* keydef = NULL;
+ char* keysizdef = NULL;
+ if (doAes) {
+ asprintf(&keydef, "#define %s \"", argv[4]);
+ fwrite(keydef, 1, strlen(keydef), outfile);
+ fwrite(cstr_key, 1, strlen(cstr_key), outfile);
+ fwrite("\"\n", 1, 2, outfile);
+ asprintf(&keysizdef, "#define %sSIZ %u\n", argv[4], (unsigned int)(sizeof(aeskey)/sizeof(aeskey[0])));
+ fwrite(keysizdef, 1, strlen(keysizdef), outfile);
+ free(cstr_key);
+ } else {
+ asprintf(&keydef, "#define %s ", argv[4]);
+ char xorkeystr[12];
+ snprintf(&xorkeystr[0], 11, "%u", xorkey);
+ xorkeystr[11] = '\0';
+ fwrite(keydef, 1, strlen(keydef), outfile);
+ fwrite(&xorkeystr[0], 1, strlen(xorkeystr), outfile);
+ fwrite("\n", 1, 1, outfile);
+ asprintf(&keysizdef, "#define %sSIZ %u\n", argv[4], (unsigned int)sizeof(xorkey));
+ fwrite(keysizdef, 1, strlen(keysizdef), outfile);
+ }
+ free(keysizdef);
+ keysizdef = NULL;
+
+ char line[MAX_LINE];
+ memset(&line[0], '\0', sizeof(line));
+ while (fgets(line, sizeof(line), infile)) {
+ char* tmp = line;
+ char* enc = NULL; char* header = NULL; char* trailer = NULL;
+ uint32_t enclen = 0;
+ bool gotStr = false;
+
+ if ( strstr(tmp, "#define") == tmp ) {
+ tmp += strlen("#define");
+ if ( (tmp = strchr(tmp, '"')) ) {
+ tmp++;
+ header = tmp;
+ char* str = strchr(tmp, '"');
+ if (str) {
+ trailer = str;
+ enclen = str-tmp;
+ enc = calloc(sizeof(char), enclen+1);
+ memcpy(enc, tmp, enclen);
+ genUnescapedBuf(enc, &enclen);
+ gotStr = true;
+ }
+ }
+ } else if ( strstr(tmp, "/*") ) {
+ if ( (tmp = strchr(tmp, ' ')) ) {
+ while (*(++tmp) == ' ') {}
+ size_t len = strlen(tmp);
+ if (strstr(tmp, "SECTION:") == tmp &&
+ tmp[len-1] == '\n' && tmp[len-2] == '/' &&
+ tmp[len-3] == '*' && tmp[len-4] == ' ') {
+ addDefineName(tmp, DT_SECTION, &cur);
+ } else if (strstr(tmp, "ENDSECTION") == tmp) {
+ addDefineName(tmp-1, DT_ENDSECTION, &cur);
+ }
+ }
+ }
+
+ if (gotStr) {
+ uint32_t newsiz = 0;
+ char* out = NULL;
+ if (doAes) {
+ out = aes_crypt_s(ctx, enc, enclen, &newsiz, true);
+ } else {
+ out = alignedCopyBuffer(enc, &enclen, xor_align);
+ xor32_byte_crypt((unsigned char*)out, enclen, xorkey);
+ newsiz = enclen;
+ }
+ char* outcstr = gencstr((unsigned char*)out, newsiz);
+
+ fwrite(&line[0], 1, header-&line[0], outfile);
+ fwrite(outcstr, 1, strlen(outcstr), outfile);
+ fwrite(trailer, 1, strlen(trailer), outfile);
+ addDefineName(&line[0], DT_DEFAULT, &cur);
+
+ free(outcstr);
+ free(out);
+ free(enc);
+ } else {
+ fwrite(&line[0], 1, strlen(line), outfile);
+ }
+
+ memset(&line[0], '\0', sizeof(line));
+ }
+
+ if (!doAes) {
+ if (addStrStructEntries(outfile, argv[4], defs, true) != 0)
+ exit(1);
+ if (addStrStructEntries(outfile, argv[4], defs, false) != 0)
+ exit(1);
+ if (addStrEnumEntries(outfile, argv[4], defs, true) != 0)
+ exit(1);
+ if (addStrEnumEntries(outfile, argv[4], defs, false) != 0)
+ exit(1);
+ }
+
+ fclose(infile);
+ fclose(outfile);
+
+ free(keydef);
+ if (doAes) {
+ aes_free_ctx(ctx);
+ }
+ exit(EXIT_SUCCESS);
+}