diff --git a/frontend/SlunkCrypt.vcxproj b/frontend/SlunkCrypt.vcxproj index 32e389c..93caa27 100644 --- a/frontend/SlunkCrypt.vcxproj +++ b/frontend/SlunkCrypt.vcxproj @@ -44,14 +44,18 @@ - + + + + - + + diff --git a/frontend/SlunkCrypt.vcxproj.filters b/frontend/SlunkCrypt.vcxproj.filters index 322b6f7..ad001d8 100644 --- a/frontend/SlunkCrypt.vcxproj.filters +++ b/frontend/SlunkCrypt.vcxproj.filters @@ -21,12 +21,18 @@ Source Files - + Source Files Source Files + + Source Files + + + Source Files + @@ -35,12 +41,18 @@ Header Files - + Header Files Header Files + + Header Files + + + Header Files + diff --git a/frontend/src/blake2.h b/frontend/src/blake2.h index e875468..0f21cdb 100644 --- a/frontend/src/blake2.h +++ b/frontend/src/blake2.h @@ -11,8 +11,8 @@ https://blake2.net. */ -#ifndef BLAKE2_H -#define BLAKE2_H +#ifndef INC_SLUNKAPP_BLAKE2_H +#define INC_SLUNKAPP_BLAKE2_H #define BLAKE2S_BLOCKBYTES 64 diff --git a/frontend/src/crypt.c b/frontend/src/crypt.c new file mode 100644 index 0000000..52425e2 --- /dev/null +++ b/frontend/src/crypt.c @@ -0,0 +1,435 @@ +/******************************************************************************/ +/* SlunkCrypt, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifdef _WIN32 +# define _CRT_SECURE_NO_WARNINGS 1 +#else +# define _GNU_SOURCE 1 +#endif + +/* Internal */ +#include "crypt.h" +#include +#include "utils.h" +#include "blake2.h" + +/* CRT */ +#include +#include +#include +#include + +// ========================================================================== +// Constants +// ========================================================================== + +static const uint64_t MAGIC_NUMBER = 0x243F6A8885A308D3ull; +static const clock_t UPDATE_INTERVAL = (clock_t)(1.5708 * CLOCKS_PER_SEC); + +#define BUFFER_SIZE 4096U + +// ========================================================================== +// Auxiliary functions +// ========================================================================== + +static int open_files(FILE **const file_in, FILE **const file_out, const CHR *const input_path, const CHR *const output_path) +{ + if (!(*file_in = FOPEN(input_path, T("rb")))) + { + FPRINTF(stderr, T("Error: Failed to open input file \"%") T(PRISTR) T("\" for reading!\n\n"), input_path); + *file_out = NULL; + return EXIT_FAILURE; + } + + if (!(*file_out = FOPEN(output_path, T("wb")))) + { + FPRINTF(stderr, T("Error: Failed to open output file \"%") T(PRISTR) T("\" for writing!\n\n"), output_path); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +// ========================================================================== +// Encrypt +// ========================================================================== + +int encrypt(const char *const passphrase, const CHR *const input_path, const CHR *const output_path, const int keep_incomplete) +{ + slunkcrypt_t ctx = SLUNKCRYPT_NULL; + FILE* file_in = NULL, * file_out = NULL; + int result = EXIT_FAILURE, status; + + if (open_files(&file_in, &file_out, input_path, output_path) != EXIT_SUCCESS) + { + goto clean_up; + } + + const uint64_t file_size = get_file_size(file_in); + if (file_size == UINT64_MAX) + { + FPUTS(T("I/O error: Failed to determine size of input file!\n\n"), stderr); + goto clean_up; + } + else if (file_size < 1U) + { + FPUTS(T("Error: Input file is empty or an unsupported type!\n\n"), stderr); + goto clean_up; + } + + FPUTS(T("Encrypting file contents, please be patient... "), stderr); + fflush(stderr); + + uint64_t nonce; + if (slunkcrypt_generate_nonce(&nonce) != SLUNKCRYPT_SUCCESS) + { + FPUTS(T("\n\nSlunkCrypt error: Failed to generate nonce!\n\n"), stderr); + goto clean_up; + } + + ctx = slunkcrypt_alloc(nonce, (const uint8_t*)passphrase, strlen(passphrase), SLUNKCRYPT_ENCRYPT); + if (!ctx) + { + FPUTS(g_slunkcrypt_abort_flag ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to initialize encryption!\n\n"), stderr); + goto clean_up; + } + + if (fwrite_ui64(nonce ^ MAGIC_NUMBER, file_out) < 1U) + { + FPUTS(T("\n\nI/O error: Failed to write nonce value!\n\n"), stderr); + goto clean_up; + } + + unsigned refresh_cycles = 0U; + clock_t clk_update = clock(); + uint64_t bytes_read = 0U; + uint8_t buffer[BUFFER_SIZE]; + + blake2s_t blake2s_state; + blake2s_init(&blake2s_state); + + FPRINTF(stderr, T("%5.1f%% "), 0.0); + fflush(stderr); + + while (bytes_read < file_size) + { + const uint64_t bytes_remaining = file_size - bytes_read; + const size_t request_len = (bytes_remaining < BUFFER_SIZE) ? ((size_t)bytes_remaining) : BUFFER_SIZE; + const size_t count = fread(buffer, sizeof(uint8_t), request_len, file_in); + if (count > 0U) + { + blake2s_update(&blake2s_state, buffer, count); + bytes_read += count; + if ((status = slunkcrypt_inplace(ctx, buffer, count)) != SLUNKCRYPT_SUCCESS) + { + FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to encrypt data!\n\n"), stderr); + goto clean_up; + } + if (fwrite(buffer, sizeof(uint8_t), count, file_out) < count) + { + FPUTS(T("\n\nI/O error: Failed to write encrypted data!\n\n"), stderr); + goto clean_up; + } + } + if (count < request_len) + { + break; /*EOF*/ + } + if (!(++refresh_cycles & 0x1F)) + { + const clock_t clk_now = clock(); + if ((clk_now < clk_update) || (clk_now - clk_update > UPDATE_INTERVAL)) + { + FPRINTF(stderr, T("\b\b\b\b\b\b\b%5.1f%% "), (bytes_read / ((double)file_size)) * 100.0); + fflush(stderr); + clk_update = clk_now; + } + } + } + + if (ferror(file_in)) + { + FPUTS(T("\n\nI/O error: Failed to read input data!\n\n"), stderr); + goto clean_up; + } + + if (bytes_read != file_size) + { + FPUTS(T("\n\nI/O error: Input file could not be fully read!\n\n"), stderr); + goto clean_up; + } + + const size_t padding = sizeof(uint64_t) - (file_size % sizeof(uint64_t)); + assert(padding && (padding <= sizeof(uint64_t))); + if (slunkcrypt_random_bytes(buffer, padding) < padding) + { + FPUTS(T("\n\nSlunkCrypt error: Failed to generate random data!\n\n"), stderr); + goto clean_up; + } + + SET_LOWBITS(buffer[padding - 1U], padding - 1U); + if ((status = slunkcrypt_inplace(ctx, buffer, padding)) != SLUNKCRYPT_SUCCESS) + { + FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to encrypt data!\n\n"), stderr); + goto clean_up; + } + + if (fwrite(buffer, sizeof(uint8_t), padding, file_out) < padding) + { + FPUTS(T("\n\nI/O error: Failed to write padding data!\n\n"), stderr); + goto clean_up; + } + + uint8_t checksum_buffer[sizeof(uint64_t)]; + store_ui64(checksum_buffer, blake2s_final(&blake2s_state)); + + if ((status = slunkcrypt_inplace(ctx, checksum_buffer, sizeof(uint64_t))) != SLUNKCRYPT_SUCCESS) + { + FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to encrypt checksum!\n\n"), stderr); + goto clean_up; + } + + if (fwrite(checksum_buffer, sizeof(uint8_t), sizeof(uint64_t), file_out) < sizeof(uint64_t)) + { + FPUTS(T("\n\nI/O error: Failed to write the checksum!\n\n"), stderr); + goto clean_up; + } + + FPRINTF(stderr, T("\b\b\b\b\b\b\b%5.1f%%\n\n"), 100.0); + + result = EXIT_SUCCESS; + + FPUTS(T("All is done.\n\n"), stderr); + fflush(stderr); + +clean_up: + + if (ctx) + { + slunkcrypt_free(ctx); + } + + if (file_out) + { + fclose(file_out); + if ((result != EXIT_SUCCESS) && (!keep_incomplete)) + { + if (REMOVE(output_path)) + { + FPUTS(T("Warning: Failed to remove incomplete output file!\n\n"), stderr); + } + } + } + + if (file_in) + { + fclose(file_in); + } + + slunkcrypt_bzero(buffer, BUFFER_SIZE); + slunkcrypt_bzero(checksum_buffer, sizeof(uint64_t)); + slunkcrypt_bzero(&blake2s_state, sizeof(blake2s_t)); + slunkcrypt_bzero(&nonce, sizeof(uint64_t)); + + return result; +} + +// ========================================================================== +// Decrypt +// ========================================================================== + +int decrypt(const char *const passphrase, const CHR *const input_path, const CHR *const output_path, const int keep_incomplete) +{ + slunkcrypt_t ctx = SLUNKCRYPT_NULL; + FILE* file_in = NULL, * file_out = NULL; + int result = EXIT_FAILURE, status; + + if (open_files(&file_in, &file_out, input_path, output_path) != EXIT_SUCCESS) + { + goto clean_up; + } + + const uint64_t file_size = get_file_size(file_in); + if (file_size == UINT64_MAX) + { + FPUTS(T("I/O error: Failed to determine size of input file!\n\n"), stderr); + goto clean_up; + } + else if (file_size < (3U * sizeof(uint64_t))) + { + FPUTS(T("Error: Input file is too small! Truncated?\n\n"), stderr); + goto clean_up; + } + else if ((file_size % sizeof(uint64_t)) != 0) + { + FPRINTF(stderr, T("Warning: File size is *not* an integer multiple of %u, ignoring excess bytes!\n\n"), (unsigned)sizeof(uint64_t)); + } + + FPUTS(T("Decrypting file contents, please be patient... "), stderr); + fflush(stderr); + + uint64_t nonce; + if (fread_ui64(&nonce, file_in) < 1U) + { + FPUTS(T("\n\nI/O error: Failed to read nonce value!\n\n"), stderr); + goto clean_up; + } + + ctx = slunkcrypt_alloc(nonce ^ MAGIC_NUMBER, (const uint8_t*)passphrase, strlen(passphrase), SLUNKCRYPT_DECRYPT); + if (!ctx) + { + FPUTS(g_slunkcrypt_abort_flag ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to initialize decryption!\n\n"), stderr); + goto clean_up; + } + + unsigned refresh_cycles = 0U; + clock_t clk_update = clock(); + uint64_t bytes_read = sizeof(uint64_t); + uint8_t buffer[BUFFER_SIZE]; + + const uint64_t read_limit = round_down(file_size, sizeof(uint64_t)) - (2U * sizeof(uint64_t)); + + blake2s_t blake2s_state; + blake2s_init(&blake2s_state); + + FPRINTF(stderr, T("%5.1f%% "), 0.0); + fflush(stderr); + + while (bytes_read < read_limit) + { + const uint64_t bytes_remaining = read_limit - bytes_read; + const size_t request_len = (bytes_remaining < BUFFER_SIZE) ? ((size_t)bytes_remaining) : BUFFER_SIZE; + const size_t count = fread(buffer, sizeof(uint8_t), request_len, file_in); + if (count > 0U) + { + bytes_read += count; + if ((status = slunkcrypt_inplace(ctx, buffer, count)) != SLUNKCRYPT_SUCCESS) + { + FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to decrypt data!\n\n"), stderr); + goto clean_up; + } + blake2s_update(&blake2s_state, buffer, count); + if (fwrite(buffer, sizeof(uint8_t), count, file_out) < count) + { + FPUTS(T("failed!\n\nI/O error: Failed to write decrypted data!\n\n"), stderr); + goto clean_up; + } + } + if (count < request_len) + { + break; /*EOF*/ + } + if (!(++refresh_cycles & 0x1F)) + { + const clock_t clk_now = clock(); + if ((clk_now < clk_update) || (clk_now - clk_update > UPDATE_INTERVAL)) + { + FPRINTF(stderr, T("\b\b\b\b\b\b\b%5.1f%% "), (bytes_read / ((double)read_limit)) * 100.0); + fflush(stderr); + clk_update = clk_now; + } + } + } + + if (ferror(file_in)) + { + FPUTS(T("\n\nI/O error: Failed to read input data!\n\n"), stderr); + goto clean_up; + } + + if (bytes_read != read_limit) + { + FPUTS(T("\n\nI/O error: Input file could not be fully read!\n\n"), stderr); + goto clean_up; + } + + if (fread(buffer, sizeof(uint8_t), sizeof(uint64_t), file_in) < sizeof(uint64_t)) + { + FPUTS(T("\n\nI/O error: Failed to read final block!\n\n"), stderr); + goto clean_up; + } + + if ((status = slunkcrypt_inplace(ctx, buffer, sizeof(uint64_t))) != SLUNKCRYPT_SUCCESS) + { + FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to decrypt data!\n\n"), stderr); + goto clean_up; + } + + const size_t padding = GET_LOWBITS(buffer[sizeof(uint64_t) - 1U]) + 1U; + assert(padding && (padding <= sizeof(uint64_t))); + if (padding != sizeof(uint64_t)) + { + const size_t count = sizeof(uint64_t) - padding; + if (fwrite(buffer, sizeof(uint8_t), count, file_out) < count) + { + FPUTS(T("failed!\n\nI/O error: Failed to write decrypted data!\n\n"), stderr); + goto clean_up; + } + blake2s_update(&blake2s_state, buffer, count); + } + + const uint64_t checksum_actual = blake2s_final(&blake2s_state); + + uint8_t checksum_buffer[sizeof(uint64_t)]; + if (fread(checksum_buffer, sizeof(uint8_t), sizeof(uint64_t), file_in) < sizeof(uint64_t)) + { + FPUTS(T("\n\nI/O error: Failed to read the checksum!\n\n"), stderr); + goto clean_up; + } + + if ((status = slunkcrypt_inplace(ctx, checksum_buffer, sizeof(uint64_t))) != SLUNKCRYPT_SUCCESS) + { + FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to decrypt checksum!\n\n"), stderr); + goto clean_up; + } + + FPRINTF(stderr, T("\b\b\b\b\b\b\b%5.1f%%\n\n"), 100.0); + + const uint64_t checksum_stored = load_ui64(checksum_buffer); + if (checksum_actual != checksum_stored) + { + FPRINTF(stderr, T("Error: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_stored, checksum_actual); + FPUTS(T("Wrong passphrase or corrupted file?\n\n"), stderr); + goto clean_up; + } + + result = EXIT_SUCCESS; + + FPUTS(T("Checksum is correct.\n\n"), stderr); + fflush(stderr); + +clean_up: + + if (ctx) + { + slunkcrypt_free(ctx); + } + + if (file_out) + { + fclose(file_out); + if ((result != EXIT_SUCCESS) && (!keep_incomplete)) + { + if (REMOVE(output_path)) + { + FPUTS(T("Warning: Failed to remove incomplete output file!\n\n"), stderr); + } + } + } + + if (file_in) + { + fclose(file_in); + } + + slunkcrypt_bzero(buffer, BUFFER_SIZE); + slunkcrypt_bzero(checksum_buffer, sizeof(uint64_t)); + slunkcrypt_bzero(&blake2s_state, sizeof(blake2s_t)); + slunkcrypt_bzero(&nonce, sizeof(uint64_t)); + slunkcrypt_bzero((void*)&checksum_stored, sizeof(uint64_t)); + slunkcrypt_bzero((void*)&checksum_actual, sizeof(uint64_t)); + + return result; +} diff --git a/frontend/src/crypt.h b/frontend/src/crypt.h new file mode 100644 index 0000000..3746d6c --- /dev/null +++ b/frontend/src/crypt.h @@ -0,0 +1,15 @@ +/******************************************************************************/ +/* SlunkCrypt, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifndef INC_SLUNKAPP_CRYPT_H +#define INC_SLUNKAPP_CRYPT_H + +#include "platform.h" +#include + +int encrypt(const char *const passphrase, const CHR *const input_path, const CHR *const output_path, const int keep_incomplete); +int decrypt(const char *const passphrase, const CHR *const input_path, const CHR *const output_path, const int keep_incomplete); + +#endif diff --git a/frontend/src/main.c b/frontend/src/main.c index 2083ba2..ed4e603 100644 --- a/frontend/src/main.c +++ b/frontend/src/main.c @@ -9,13 +9,11 @@ # define _GNU_SOURCE 1 #endif -/* API */ +/* Internal */ #include - -/* CLI */ #include "utils.h" -#include "blake2.h" -#include "test.h" +#include "crypt.h" +#include "selftest.h" /* CRT */ #include @@ -23,14 +21,11 @@ #include #include #include -#include // ========================================================================== // Constants // ========================================================================== -#define BUFFER_SIZE 4096U - #define MODE_HELP 0 #define MODE_VERS 1 #define MODE_ENCR 2 @@ -59,10 +54,6 @@ static const char PASSWD_SYMBOLS[] = static const size_t RCMD_PWDLEN_LENGTH = 12U; static const size_t DFLT_PWDLEN_LENGTH = 20U; -static const clock_t UPDATE_INTERVAL = (clock_t)(1.5708 * CLOCKS_PER_SEC); - -static const uint64_t MAGIC_NUMBER = 0x243F6A8885A308D3ull; - // ========================================================================== // Auxiliary functions // ========================================================================== @@ -241,32 +232,23 @@ clean_up: return result; } -static int open_files(FILE **const file_in, FILE **const file_out, const CHR *const input_path, const CHR *const output_path) +static int keep_incomplete_files(void) { - if (!(*file_in = FOPEN(input_path, T("rb")))) - { - FPRINTF(stderr, T("Error: Failed to open input file \"%") T(PRISTR) T("\" for reading!\n\n"), input_path); - *file_out = NULL; - return EXIT_FAILURE; - } - - if (!(*file_out = FOPEN(output_path, T("wb")))) - { - FPRINTF(stderr, T("Error: Failed to open output file \"%") T(PRISTR) T("\" for writing!\n\n"), output_path); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} - -static int remove_incomplete_files(void) -{ - const CHR* const keep_files = GETENV(ENV_KEEPFILE); + const CHR *const keep_files = GETENV(ENV_KEEPFILE); if (keep_files) { - return (!STRTOUL(keep_files)); + return BOOLIFY(STRTOUL(keep_files)); + } + return 0; +} + +static void check_excess_arguments(const int argc, int maximum) +{ + if (argc > maximum) + { + FPUTS(T("Warning: Excess command-line argument(s) will be ignored!\n\n"), stderr); + fflush(stderr); } - return 1; } static void sigint_handler(const int sig) @@ -277,525 +259,6 @@ static void sigint_handler(const int sig) } } -// ========================================================================== -// Encrypt -// ========================================================================== - -static int encrypt(const char* const passphrase, const CHR* const input_path, const CHR* const output_path) -{ - slunkcrypt_t ctx = SLUNKCRYPT_NULL; - FILE *file_in = NULL, *file_out = NULL; - int result = EXIT_FAILURE, status; - - if (open_files(&file_in, &file_out, input_path, output_path) != EXIT_SUCCESS) - { - goto clean_up; - } - - const uint64_t file_size = get_file_size(file_in); - if (file_size == UINT64_MAX) - { - FPUTS(T("I/O error: Failed to determine size of input file!\n\n"), stderr); - goto clean_up; - } - else if (file_size < 1U) - { - FPUTS(T("Error: Input file is empty or an unsupported type!\n\n"), stderr); - goto clean_up; - } - - FPUTS(T("Encrypting file contents, please be patient... "), stderr); - fflush(stderr); - - uint64_t nonce; - if (slunkcrypt_generate_nonce(&nonce) != SLUNKCRYPT_SUCCESS) - { - FPUTS(T("\n\nSlunkCrypt error: Failed to generate nonce!\n\n"), stderr); - goto clean_up; - } - - ctx = slunkcrypt_alloc(nonce, (const uint8_t*)passphrase, strlen(passphrase), SLUNKCRYPT_ENCRYPT); - if (!ctx) - { - FPUTS(g_slunkcrypt_abort_flag ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to initialize encryption!\n\n"), stderr); - goto clean_up; - } - - if (fwrite_ui64(nonce ^ MAGIC_NUMBER, file_out) < 1U) - { - FPUTS(T("\n\nI/O error: Failed to write nonce value!\n\n"), stderr); - goto clean_up; - } - - unsigned refresh_cycles = 0U; - clock_t clk_update = clock(); - uint64_t bytes_read = 0U; - uint8_t buffer[BUFFER_SIZE]; - - blake2s_t blake2s_state; - blake2s_init(&blake2s_state); - - FPRINTF(stderr, T("%5.1f%% "), 0.0); - fflush(stderr); - - while (bytes_read < file_size) - { - const uint64_t bytes_remaining = file_size - bytes_read; - const size_t request_len = (bytes_remaining < BUFFER_SIZE) ? ((size_t)bytes_remaining) : BUFFER_SIZE; - const size_t count = fread(buffer, sizeof(uint8_t), request_len, file_in); - if (count > 0U) - { - blake2s_update(&blake2s_state, buffer, count); - bytes_read += count; - if ((status = slunkcrypt_inplace(ctx, buffer, count)) != SLUNKCRYPT_SUCCESS) - { - FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to encrypt data!\n\n"), stderr); - goto clean_up; - } - if (fwrite(buffer, sizeof(uint8_t), count, file_out) < count) - { - FPUTS(T("\n\nI/O error: Failed to write encrypted data!\n\n"), stderr); - goto clean_up; - } - } - if (count < request_len) - { - break; /*EOF*/ - } - if (!(++refresh_cycles & 0x1F)) - { - const clock_t clk_now = clock(); - if ((clk_now < clk_update) || (clk_now - clk_update > UPDATE_INTERVAL)) - { - FPRINTF(stderr, T("\b\b\b\b\b\b\b%5.1f%% "), (bytes_read / ((double)file_size)) * 100.0); - fflush(stderr); - clk_update = clk_now; - } - } - } - - if (ferror(file_in)) - { - FPUTS(T("\n\nI/O error: Failed to read input data!\n\n"), stderr); - goto clean_up; - } - - if (bytes_read != file_size) - { - FPUTS(T("\n\nI/O error: Input file could not be fully read!\n\n"), stderr); - goto clean_up; - } - - const size_t padding = sizeof(uint64_t) - (file_size % sizeof(uint64_t)); - assert(padding && (padding <= sizeof(uint64_t))); - if (slunkcrypt_random_bytes(buffer, padding) < padding) - { - FPUTS(T("\n\nSlunkCrypt error: Failed to generate random data!\n\n"), stderr); - goto clean_up; - } - - SET_LOWBITS(buffer[padding - 1U], padding - 1U); - if ((status = slunkcrypt_inplace(ctx, buffer, padding)) != SLUNKCRYPT_SUCCESS) - { - FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to encrypt data!\n\n"), stderr); - goto clean_up; - } - - if (fwrite(buffer, sizeof(uint8_t), padding, file_out) < padding) - { - FPUTS(T("\n\nI/O error: Failed to write padding data!\n\n"), stderr); - goto clean_up; - } - - uint8_t checksum_buffer[sizeof(uint64_t)]; - store_ui64(checksum_buffer, blake2s_final(&blake2s_state)); - - if ((status = slunkcrypt_inplace(ctx, checksum_buffer, sizeof(uint64_t))) != SLUNKCRYPT_SUCCESS) - { - FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to encrypt checksum!\n\n"), stderr); - goto clean_up; - } - - if (fwrite(checksum_buffer, sizeof(uint8_t), sizeof(uint64_t), file_out) < sizeof(uint64_t)) - { - FPUTS(T("\n\nI/O error: Failed to write the checksum!\n\n"), stderr); - goto clean_up; - } - - FPRINTF(stderr, T("\b\b\b\b\b\b\b%5.1f%%\n\n"), 100.0); - - result = EXIT_SUCCESS; - - FPUTS(T("All is done.\n\n"), stderr); - fflush(stderr); - -clean_up: - - if (ctx) - { - slunkcrypt_free(ctx); - } - - if (file_out) - { - fclose(file_out); - if ((result != EXIT_SUCCESS) && remove_incomplete_files()) - { - if (REMOVE(output_path)) - { - FPUTS(T("Warning: Failed to remove incomplete output file!\n\n"), stderr); - } - } - } - - if (file_in) - { - fclose(file_in); - } - - slunkcrypt_bzero(buffer, BUFFER_SIZE); - slunkcrypt_bzero(checksum_buffer, sizeof(uint64_t)); - slunkcrypt_bzero(&blake2s_state, sizeof(blake2s_t)); - slunkcrypt_bzero(&nonce, sizeof(uint64_t)); - - return result; -} - -// ========================================================================== -// Decrypt -// ========================================================================== - -static int decrypt(const char* const passphrase, const CHR* const input_path, const CHR* const output_path) -{ - slunkcrypt_t ctx = SLUNKCRYPT_NULL; - FILE *file_in = NULL, *file_out = NULL; - int result = EXIT_FAILURE, status; - - if (open_files(&file_in, &file_out, input_path, output_path) != EXIT_SUCCESS) - { - goto clean_up; - } - - const uint64_t file_size = get_file_size(file_in); - if (file_size == UINT64_MAX) - { - FPUTS(T("I/O error: Failed to determine size of input file!\n\n"), stderr); - goto clean_up; - } - else if (file_size < (3U * sizeof(uint64_t))) - { - FPUTS(T("Error: Input file is too small! Truncated?\n\n"), stderr); - goto clean_up; - } - else if ((file_size % sizeof(uint64_t)) != 0) - { - FPRINTF(stderr, T("Warning: File size is *not* an integer multiple of %u, ignoring excess bytes!\n\n"), (unsigned)sizeof(uint64_t)); - } - - FPUTS(T("Decrypting file contents, please be patient... "), stderr); - fflush(stderr); - - uint64_t nonce; - if (fread_ui64(&nonce, file_in) < 1U) - { - FPUTS(T("\n\nI/O error: Failed to read nonce value!\n\n"), stderr); - goto clean_up; - } - - ctx = slunkcrypt_alloc(nonce ^ MAGIC_NUMBER, (const uint8_t*)passphrase, strlen(passphrase), SLUNKCRYPT_DECRYPT); - if (!ctx) - { - FPUTS(g_slunkcrypt_abort_flag ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to initialize decryption!\n\n"), stderr); - goto clean_up; - } - - unsigned refresh_cycles = 0U; - clock_t clk_update = clock(); - uint64_t bytes_read = sizeof(uint64_t); - uint8_t buffer[BUFFER_SIZE]; - - const uint64_t read_limit = round_down(file_size, sizeof(uint64_t)) - (2U * sizeof(uint64_t)); - - blake2s_t blake2s_state; - blake2s_init(&blake2s_state); - - FPRINTF(stderr, T("%5.1f%% "), 0.0); - fflush(stderr); - - while (bytes_read < read_limit) - { - const uint64_t bytes_remaining = read_limit - bytes_read; - const size_t request_len = (bytes_remaining < BUFFER_SIZE) ? ((size_t)bytes_remaining) : BUFFER_SIZE; - const size_t count = fread(buffer, sizeof(uint8_t), request_len, file_in); - if (count > 0U) - { - bytes_read += count; - if ((status = slunkcrypt_inplace(ctx, buffer, count)) != SLUNKCRYPT_SUCCESS) - { - FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to decrypt data!\n\n"), stderr); - goto clean_up; - } - blake2s_update(&blake2s_state, buffer, count); - if (fwrite(buffer, sizeof(uint8_t), count, file_out) < count) - { - FPUTS(T("failed!\n\nI/O error: Failed to write decrypted data!\n\n"), stderr); - goto clean_up; - } - } - if (count < request_len) - { - break; /*EOF*/ - } - if (!(++refresh_cycles & 0x1F)) - { - const clock_t clk_now = clock(); - if ((clk_now < clk_update) || (clk_now - clk_update > UPDATE_INTERVAL)) - { - FPRINTF(stderr, T("\b\b\b\b\b\b\b%5.1f%% "), (bytes_read / ((double)read_limit)) * 100.0); - fflush(stderr); - clk_update = clk_now; - } - } - } - - if (ferror(file_in)) - { - FPUTS(T("\n\nI/O error: Failed to read input data!\n\n"), stderr); - goto clean_up; - } - - if (bytes_read != read_limit) - { - FPUTS(T("\n\nI/O error: Input file could not be fully read!\n\n"), stderr); - goto clean_up; - } - - if (fread(buffer, sizeof(uint8_t), sizeof(uint64_t), file_in) < sizeof(uint64_t)) - { - FPUTS(T("\n\nI/O error: Failed to read final block!\n\n"), stderr); - goto clean_up; - } - - if ((status = slunkcrypt_inplace(ctx, buffer, sizeof(uint64_t))) != SLUNKCRYPT_SUCCESS) - { - FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to decrypt data!\n\n"), stderr); - goto clean_up; - } - - const size_t padding = GET_LOWBITS(buffer[sizeof(uint64_t) - 1U]) + 1U; - assert(padding && (padding <= sizeof(uint64_t))); - if (padding != sizeof(uint64_t)) - { - const size_t count = sizeof(uint64_t) - padding; - if (fwrite(buffer, sizeof(uint8_t), count, file_out) < count) - { - FPUTS(T("failed!\n\nI/O error: Failed to write decrypted data!\n\n"), stderr); - goto clean_up; - } - blake2s_update(&blake2s_state, buffer, count); - } - - const uint64_t checksum_actual = blake2s_final(&blake2s_state); - - uint8_t checksum_buffer[sizeof(uint64_t)]; - if (fread(checksum_buffer, sizeof(uint8_t), sizeof(uint64_t), file_in) < sizeof(uint64_t)) - { - FPUTS(T("\n\nI/O error: Failed to read the checksum!\n\n"), stderr); - goto clean_up; - } - - if ((status = slunkcrypt_inplace(ctx, checksum_buffer, sizeof(uint64_t))) != SLUNKCRYPT_SUCCESS) - { - FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to decrypt checksum!\n\n"), stderr); - goto clean_up; - } - - FPRINTF(stderr, T("\b\b\b\b\b\b\b%5.1f%%\n\n"), 100.0); - - const uint64_t checksum_stored = load_ui64(checksum_buffer); - if (checksum_actual != checksum_stored) - { - FPRINTF(stderr, T("Error: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_stored, checksum_actual); - FPUTS(T("Wrong passphrase or corrupted file?\n\n"), stderr); - goto clean_up; - } - - result = EXIT_SUCCESS; - - FPUTS(T("Checksum is correct.\n\n"), stderr); - fflush(stderr); - -clean_up: - - if (ctx) - { - slunkcrypt_free(ctx); - } - - if (file_out) - { - fclose(file_out); - if ((result != EXIT_SUCCESS) && remove_incomplete_files()) - { - if (REMOVE(output_path)) - { - FPUTS(T("Warning: Failed to remove incomplete output file!\n\n"), stderr); - } - } - } - - if (file_in) - { - fclose(file_in); - } - - slunkcrypt_bzero(buffer, BUFFER_SIZE); - slunkcrypt_bzero(checksum_buffer, sizeof(uint64_t)); - slunkcrypt_bzero(&blake2s_state, sizeof(blake2s_t)); - slunkcrypt_bzero(&nonce, sizeof(uint64_t)); - slunkcrypt_bzero((void*)&checksum_stored, sizeof(uint64_t)); - slunkcrypt_bzero((void*)&checksum_actual, sizeof(uint64_t)); - - return result; -} - -// ========================================================================== -// Self-test -// ========================================================================== - -static int run_test_case(const char *const message, const uint64_t nonce, const uint64_t checksum_message, const uint64_t checksum_expected) -{ - static const char* const TEST_PASSPHRASE = "OrpheanBeh0lderScry!Doubt"; - - int status, result = EXIT_FAILURE; - const size_t length = strlen(message) + 1U; - slunkcrypt_t ctx = SLUNKCRYPT_NULL; - - char* const text_temp = strdup(message); - if (!text_temp) - { - FPUTS(T("\n\nWhoops: Failed to allocate text buffer!\n\n"), stderr); - goto clean_up; - } - - const uint64_t checksum_original = blake2s_compute((uint8_t*)text_temp, length); - if (checksum_original != checksum_message) - { - FPRINTF(stderr, T("\n\nWhoops: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_message, checksum_original); - goto clean_up; - } - - ctx = slunkcrypt_alloc(nonce, (const uint8_t*)TEST_PASSPHRASE, strlen(TEST_PASSPHRASE), SLUNKCRYPT_ENCRYPT); - if (!ctx) - { - FPUTS(g_slunkcrypt_abort_flag ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to initialize encoder!\n\n"), stderr); - goto clean_up; - } - - status = slunkcrypt_inplace(ctx, (uint8_t*)text_temp, length); - if (status != SLUNKCRYPT_SUCCESS) - { - FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to encrypt the message!\n\n"), stderr); - goto clean_up; - } - - if (strncmp(message, text_temp, length) == 0) - { - FPUTS(T("\n\nWhoops: Encrypted message equals the original message!\n\n"), stderr); - goto clean_up; - } - - const uint64_t checksum_encrypted = blake2s_compute((uint8_t*)text_temp, length); - if (checksum_encrypted != checksum_expected) - { - FPRINTF(stderr, T("\n\nWhoops: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_expected, checksum_encrypted); - goto clean_up; - } - - status = slunkcrypt_reset(ctx, nonce, (const uint8_t*)TEST_PASSPHRASE, strlen(TEST_PASSPHRASE), SLUNKCRYPT_DECRYPT); - if (status != SLUNKCRYPT_SUCCESS) - { - FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to initialize decoder!\n\n"), stderr); - goto clean_up; - } - - status = slunkcrypt_inplace(ctx, (uint8_t*)text_temp, length); - if (status != SLUNKCRYPT_SUCCESS) - { - FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to decrypt the message!\n\n"), stderr); - goto clean_up; - } - - if (memcmp(message, text_temp, length * sizeof(char)) != 0) - { - FPUTS(T("\n\nWhoops: Decrypted message does *not* match the original message!\n\n"), stderr); - goto clean_up; - } - - const uint64_t checksum_decrypted = blake2s_compute((uint8_t*)text_temp, length); - if (checksum_decrypted != checksum_original) - { - FPRINTF(stderr, T("\n\nWhoops: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_original, checksum_decrypted); - goto clean_up; - } - - result = EXIT_SUCCESS; - -clean_up: - - if (ctx) - { - slunkcrypt_free(ctx); - } - - if (text_temp) - { - slunkcrypt_bzero(text_temp, strlen(text_temp)); - free(text_temp); - } - - return result; -} - -static int run_self_test(void) -{ - static const uint64_t TEST_NONCE[] = { 0x243F6A8885A308D3, 0x13198A2E03707344 }; - const struct - { - const char* text; - uint64_t check_orig, check_encr[2U]; - } - TEST_STAGE[] = - { - { TEST_DATA_0, TEST_CHCK_ORIG_0, { TEST_CHCK_ENCR_0[0U], TEST_CHCK_ENCR_0[1U] } }, - { TEST_DATA_1, TEST_CHCK_ORIG_1, { TEST_CHCK_ENCR_1[0U], TEST_CHCK_ENCR_1[1U] } }, - { TEST_DATA_2, TEST_CHCK_ORIG_2, { TEST_CHCK_ENCR_2[0U], TEST_CHCK_ENCR_2[1U] } }, - { TEST_DATA_3, TEST_CHCK_ORIG_3, { TEST_CHCK_ENCR_3[0U], TEST_CHCK_ENCR_3[1U] } }, - }; - - const size_t total = ARRAY_SIZE(TEST_NONCE) * ARRAY_SIZE(TEST_STAGE); - FPRINTF(stderr, T("Self-test is in progress, please be patient... stage %u/%u "), 0U, (unsigned)total); - fflush(stderr); - - for (size_t i = 0U, count = 0U; i < ARRAY_SIZE(TEST_STAGE); ++i) - { - for (size_t j = 0U; j < ARRAY_SIZE(TEST_NONCE); ++j) - { - FPRINTF(stderr, T("\b\b\b\b%u/%u "), (unsigned)++count, (unsigned)total); - fflush(stderr); - if (run_test_case(TEST_STAGE[i].text, TEST_NONCE[j], TEST_STAGE[i].check_orig, TEST_STAGE[i].check_encr[j]) != EXIT_SUCCESS) - { - return EXIT_FAILURE; - } - } - } - - FPRINTF(stderr, T("\b\b\b\b%u/%u\n\nCompleted successfully.\n\n"), (unsigned)total, (unsigned)total); - fflush(stderr); - - return EXIT_SUCCESS; -} - // ========================================================================== // Main function // ========================================================================== @@ -834,10 +297,12 @@ int MAIN(const int argc, CHR *const argv[]) case MODE_DECR: break; /*fallthrough*/ case MODE_PASS: + check_excess_arguments(argc, 3); result = generate_passphrase((argc > 2) ? STRTOUL(argv[2U]) : DFLT_PWDLEN_LENGTH); goto clean_up; case MODE_TEST: - result = run_self_test(); + check_excess_arguments(argc, 2); + result = run_selftest_routine(); goto clean_up; default: FPRINTF(stderr, T("Error: The specified command \"%") T(PRISTR) T("\" is unknown!\n\n"), argv[1U]); @@ -850,10 +315,7 @@ int MAIN(const int argc, CHR *const argv[]) goto clean_up; } - if (argc > 5) - { - FPUTS(T("Warning: Excess command-line argument(s) will be ignored!\n\n"), stderr); - } + check_excess_arguments(argc, 5); const CHR *const passphrase = PW_FROM_ENV ? GETENV(ENV_PASSWORD) : argv[2U]; const CHR *const input_file = argv[PW_FROM_ENV ? 2U : 3U], *const output_file = argv[PW_FROM_ENV ? 3U : 4U]; @@ -920,14 +382,15 @@ int MAIN(const int argc, CHR *const argv[]) /* ----------------------------------------------------- */ const clock_t clk_start = clock(); + const int keep_incomplete = keep_incomplete_files(); switch (slunk_mode) { case MODE_ENCR: - result = encrypt(passphrase_buffer, input_file, output_file); + result = encrypt(passphrase_buffer, input_file, output_file, keep_incomplete); break; case MODE_DECR: - result = decrypt(passphrase_buffer, input_file, output_file); + result = decrypt(passphrase_buffer, input_file, output_file, keep_incomplete); break; default: FPUTS(T("Unexpected mode encountered!\n\n"), stderr); diff --git a/frontend/src/selftest.c b/frontend/src/selftest.c new file mode 100644 index 0000000..fdb8d3c --- /dev/null +++ b/frontend/src/selftest.c @@ -0,0 +1,160 @@ +/******************************************************************************/ +/* SlunkCrypt, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifdef _WIN32 +# define _CRT_SECURE_NO_WARNINGS 1 +#else +# define _GNU_SOURCE 1 +#endif + +/* Internal */ +#include "crypt.h" +#include +#include "utils.h" +#include "test_data.h" +#include "blake2.h" + +/* CRT */ +#include +#include +#include +#include + +// ========================================================================== +// Self-test routines +// ========================================================================== + +static int run_testcase(const char* const message, const uint64_t nonce, const uint64_t checksum_message, const uint64_t checksum_expected) +{ + static const char* const TEST_PASSPHRASE = "OrpheanBeh0lderScry!Doubt"; + + int status, result = EXIT_FAILURE; + const size_t length = strlen(message) + 1U; + slunkcrypt_t ctx = SLUNKCRYPT_NULL; + + char* const text_temp = strdup(message); + if (!text_temp) + { + FPUTS(T("\n\nWhoops: Failed to allocate text buffer!\n\n"), stderr); + goto clean_up; + } + + const uint64_t checksum_original = blake2s_compute((uint8_t*)text_temp, length); + if (checksum_original != checksum_message) + { + FPRINTF(stderr, T("\n\nWhoops: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_message, checksum_original); + goto clean_up; + } + + ctx = slunkcrypt_alloc(nonce, (const uint8_t*)TEST_PASSPHRASE, strlen(TEST_PASSPHRASE), SLUNKCRYPT_ENCRYPT); + if (!ctx) + { + FPUTS(g_slunkcrypt_abort_flag ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to initialize encoder!\n\n"), stderr); + goto clean_up; + } + + status = slunkcrypt_inplace(ctx, (uint8_t*)text_temp, length); + if (status != SLUNKCRYPT_SUCCESS) + { + FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to encrypt the message!\n\n"), stderr); + goto clean_up; + } + + if (strncmp(message, text_temp, length) == 0) + { + FPUTS(T("\n\nWhoops: Encrypted message equals the original message!\n\n"), stderr); + goto clean_up; + } + + const uint64_t checksum_encrypted = blake2s_compute((uint8_t*)text_temp, length); + if (checksum_encrypted != checksum_expected) + { + FPRINTF(stderr, T("\n\nWhoops: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_expected, checksum_encrypted); + goto clean_up; + } + + status = slunkcrypt_reset(ctx, nonce, (const uint8_t*)TEST_PASSPHRASE, strlen(TEST_PASSPHRASE), SLUNKCRYPT_DECRYPT); + if (status != SLUNKCRYPT_SUCCESS) + { + FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to initialize decoder!\n\n"), stderr); + goto clean_up; + } + + status = slunkcrypt_inplace(ctx, (uint8_t*)text_temp, length); + if (status != SLUNKCRYPT_SUCCESS) + { + FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to decrypt the message!\n\n"), stderr); + goto clean_up; + } + + if (memcmp(message, text_temp, length * sizeof(char)) != 0) + { + FPUTS(T("\n\nWhoops: Decrypted message does *not* match the original message!\n\n"), stderr); + goto clean_up; + } + + const uint64_t checksum_decrypted = blake2s_compute((uint8_t*)text_temp, length); + if (checksum_decrypted != checksum_original) + { + FPRINTF(stderr, T("\n\nWhoops: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_original, checksum_decrypted); + goto clean_up; + } + + result = EXIT_SUCCESS; + +clean_up: + + if (ctx) + { + slunkcrypt_free(ctx); + } + + if (text_temp) + { + slunkcrypt_bzero(text_temp, strlen(text_temp)); + free(text_temp); + } + + return result; +} + +int run_selftest_routine(void) +{ + static const uint64_t TEST_NONCE[] = { 0x243F6A8885A308D3, 0x13198A2E03707344 }; + const struct + { + const char* text; + uint64_t check_orig, check_encr[2U]; + } + TEST_STAGE[] = + { + { TEST_DATA_0, TEST_CHCK_ORIG_0, { TEST_CHCK_ENCR_0[0U], TEST_CHCK_ENCR_0[1U] } }, + { TEST_DATA_1, TEST_CHCK_ORIG_1, { TEST_CHCK_ENCR_1[0U], TEST_CHCK_ENCR_1[1U] } }, + { TEST_DATA_2, TEST_CHCK_ORIG_2, { TEST_CHCK_ENCR_2[0U], TEST_CHCK_ENCR_2[1U] } }, + { TEST_DATA_3, TEST_CHCK_ORIG_3, { TEST_CHCK_ENCR_3[0U], TEST_CHCK_ENCR_3[1U] } }, + }; + + const size_t total = ARRAY_SIZE(TEST_NONCE) * ARRAY_SIZE(TEST_STAGE); + FPRINTF(stderr, T("Self-test is in progress, please be patient... stage %u/%u "), 0U, (unsigned)total); + fflush(stderr); + + for (size_t i = 0U, count = 0U; i < ARRAY_SIZE(TEST_STAGE); ++i) + { + for (size_t j = 0U; j < ARRAY_SIZE(TEST_NONCE); ++j) + { + FPRINTF(stderr, T("\b\b\b\b%u/%u "), (unsigned)++count, (unsigned)total); + fflush(stderr); + if (run_testcase(TEST_STAGE[i].text, TEST_NONCE[j], TEST_STAGE[i].check_orig, TEST_STAGE[i].check_encr[j]) != EXIT_SUCCESS) + { + return EXIT_FAILURE; + } + } + } + + FPRINTF(stderr, T("\b\b\b\b%u/%u\n\nCompleted successfully.\n\n"), (unsigned)total, (unsigned)total); + fflush(stderr); + + return EXIT_SUCCESS; +} diff --git a/frontend/src/selftest.h b/frontend/src/selftest.h new file mode 100644 index 0000000..cd44249 --- /dev/null +++ b/frontend/src/selftest.h @@ -0,0 +1,14 @@ +/******************************************************************************/ +/* SlunkCrypt, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifndef INC_SLUNKAPP_SELFTEST_H +#define INC_SLUNKAPP_SELFTEST_H + +#include "platform.h" +#include + +int run_selftest_routine(void); + +#endif diff --git a/frontend/src/test.c b/frontend/src/test_data.c similarity index 99% rename from frontend/src/test.c rename to frontend/src/test_data.c index 476e593..23e2d7c 100644 --- a/frontend/src/test.c +++ b/frontend/src/test_data.c @@ -3,7 +3,7 @@ /* This work has been released under the CC0 1.0 Universal license! */ /******************************************************************************/ -#include "test.h" +#include "test_data.h" // ========================================================================== // Test #1 diff --git a/frontend/src/test.h b/frontend/src/test_data.h similarity index 90% rename from frontend/src/test.h rename to frontend/src/test_data.h index e8ec9c6..5896c79 100644 --- a/frontend/src/test.h +++ b/frontend/src/test_data.h @@ -3,6 +3,9 @@ /* This work has been released under the CC0 1.0 Universal license! */ /******************************************************************************/ +#ifndef INC_SLUNKAPP_TEST_DATA_H +#define INC_SLUNKAPP_TEST_DATA_H + #include extern const char* const TEST_DATA_0; @@ -14,3 +17,5 @@ extern const uint64_t TEST_CHCK_ORIG_0, TEST_CHCK_ENCR_0[2U]; extern const uint64_t TEST_CHCK_ORIG_1, TEST_CHCK_ENCR_1[2U]; extern const uint64_t TEST_CHCK_ORIG_2, TEST_CHCK_ENCR_2[2U]; extern const uint64_t TEST_CHCK_ORIG_3, TEST_CHCK_ENCR_3[2U]; + +#endif diff --git a/frontend/src/utils.c b/frontend/src/utils.c index 8658ffd..ea6910e 100644 --- a/frontend/src/utils.c +++ b/frontend/src/utils.c @@ -11,8 +11,8 @@ #endif /* Internal */ -#include #include "utils.h" +#include /* CRT */ #include diff --git a/frontend/src/utils.h b/frontend/src/utils.h index c3b62fe..4b9770c 100644 --- a/frontend/src/utils.h +++ b/frontend/src/utils.h @@ -3,8 +3,8 @@ /* This work has been released under the CC0 1.0 Universal license! */ /******************************************************************************/ -#ifndef INC_UTILS_H -#define INC_UTILS_H +#ifndef INC_SLUNKAPP_UTILS_H +#define INC_SLUNKAPP_UTILS_H #include "platform.h" #include @@ -26,8 +26,10 @@ const CHR *get_file_name(const CHR *path); uint64_t round_down(const uint64_t value, const uint64_t base); #define ARRAY_SIZE(X) (sizeof((X)) / sizeof(*(X))) +#define BOOLIFY(X) (!!(X)) #define BOUND(MIN,VAL,MAX) (((VAL) < (MIN)) ? (MIN) : (((VAL) > (MAX)) ? (MAX) : (VAL))) #define STARTS_WITH(X,Y) (!STRNICMP((X), (Y), STRLEN((Y)))) #define GET_LOWBITS(X) ((X) & 0x07) #define SET_LOWBITS(X,Y) do { X = ((X) & 0xF8) | ((Y) & 0x07); } while(0) + #endif