0xd80c07cd676f8394ULL, 0x9afce626ce85b507ULL,
};
+static void erase(void *const ptr, const size_t length)
+{
+ volatile uint8_t* buffer = ptr;
+ for (size_t i = 0U; i < length; ++i)
+ {
+ buffer[i] = 0U;
+ }
+}
static char* utf16_to_bytes(const wchar_t* const input, const UINT code_page)
{
fputs("\"\n\n", stderr);
}
-static int encrypt(const wchar_t* const passphrase, const wchar_t* const input, const wchar_t* const output)
+static int open_files(FILE** const fin, FILE** const fout, const wchar_t* const input, const wchar_t* const output)
{
- char* passphrase_utf8 = utf16_to_bytes(passphrase, CP_UTF8);
- if (!passphrase_utf8)
+ *fin = _wfopen(input, L"rb");
+ if (!(*fin))
{
- fputws(L"Error: Failed to convert passphrase to UTF-8 format!\n\n", stderr);
+ fputws(L"Error: Failed to open input file for reading!\n\n", stderr);
return 1;
}
- FILE *fin = _wfopen(input, L"rb");
- if (!fin)
+ *fout = _wfopen(output, L"wb");
+ if (!(*fout))
{
- fputws(L"Error: Failed to open input file!\n\n", stderr);
- free(passphrase_utf8);
+ fputws(L"Error: Failed to open output file for writing!\n\n", stderr);
+ fclose(*fin);
return 1;
}
- FILE* fout = _wfopen(output, L"wb");
- if (!fout)
+ return 0;
+}
+
+static uint64_t get_file_size(FILE *const file)
+{
+ struct _stati64 stat;
+ if (_fstati64(_fileno(file), &stat) != 0)
{
- fputws(L"Error: Failed to open output file!\n\n", stderr);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ fputws(L"I/O error: Failed to determine size of input file!\n\n", stderr);
+ return UINT64_MAX;
+ }
+ return (stat.st_size >= 0) ? ((uint64_t)stat.st_size) : 0U;
+}
+
+static int encrypt(const wchar_t* const passphrase, const wchar_t* const input, const wchar_t* const output)
+{
+ mcrypt_t ctx = NULL;
+ FILE *fin = NULL, *fout = NULL;
+ int result = -1;
+
+ char *const passphrase_utf8 = utf16_to_bytes(passphrase, CP_UTF8);
+ if (!passphrase_utf8)
+ {
+ fputws(L"Error: Failed to convert passphrase to UTF-8 format!\n\n", stderr);
+ goto clean_up;
+ }
+
+ if (open_files(&fin, &fout, input, output) != 0)
+ {
+ goto clean_up;;
}
uint64_t seed;
if (mcrypt_generate_seed(&seed) != 0)
{
fputws(L"MCrypt error: Failed to generate seed!\n\n", stderr);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
if (fwrite(&seed, sizeof(uint64_t), 1U, fout) < 1U)
{
- fputws(L"I/O error: Failed to write encrypted data!\n\n", stderr);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ fputws(L"I/O error: Failed to write seed value!\n\n", stderr);
+ goto clean_up;
}
- const mcrypt_t ctx = mcrypt_init(seed, passphrase_utf8);
+ ctx = mcrypt_alloc(seed, passphrase_utf8);
if (!ctx)
{
fputws(L"MCrypt error: Failed to initialize encryption!\n\n", stderr);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
fputws(L"Encrypting, please be patient... ", stderr);
if (ferror(fin))
{
fputws(L"failed!\n\nI/O error: Failed to read input data!\n\n", stderr);
- mcrypt_free(ctx);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
if (count > 0U)
{
if (mcrypt_enc_process_inplace(ctx, buffer, count) != 0)
{
fputws(L"failed!\n\nMCrypt error: Failed to encrypt data!\n\n", stderr);
- mcrypt_free(ctx);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
if (fwrite(buffer, sizeof(uint8_t), count, fout) < count)
{
fputws(L"failed!\n\nI/O error: Failed to write encrypted data!\n\n", stderr);
- mcrypt_free(ctx);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
}
}
if (fwrite(&crc_actual, sizeof(uint64_t), 1U, fout) < 1U)
{
fputws(L"failed!\n\nI/O error: Failed to write CRC checksum!\n\n", stderr);
+ goto clean_up;
+ }
+
+ result = 0;
+
+ fputws(L"done.\n\n", stderr);
+ fflush(stderr);
+
+clean_up:
+
+ if (ctx)
+ {
mcrypt_free(ctx);
+ }
+
+ if (fout)
+ {
fclose(fout);
+ }
+
+ if (fin)
+ {
fclose(fin);
- free(passphrase_utf8);
- return 1;
}
- fputws(L"done.\n\n", stderr);
+ if (passphrase_utf8)
+ {
+ erase(passphrase_utf8, strlen(passphrase_utf8));
+ free(passphrase_utf8);
+ }
- mcrypt_free(ctx);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 0;
+ return result;
}
static int decrypt(const wchar_t* const passphrase, const wchar_t* const input, const wchar_t* const output)
{
- char* passphrase_utf8 = utf16_to_bytes(passphrase, CP_UTF8);
+ mcrypt_t ctx = NULL;
+ FILE *fin = NULL, *fout = NULL;
+ int result = -1;
+
+ char *const passphrase_utf8 = utf16_to_bytes(passphrase, CP_UTF8);
if (!passphrase_utf8)
{
fputws(L"Error: Failed to convert passphrase to UTF-8 format!\n\n", stderr);
- return 1;
+ goto clean_up;
}
- FILE* fin = _wfopen(input, L"rb");
- if (!fin)
+ if (open_files(&fin, &fout, input, output) != 0)
{
- fputws(L"Error: Failed to open input file!\n\n", stderr);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
- FILE* fout = _wfopen(output, L"wb");
- if (!fout)
+ const uint64_t file_size = get_file_size(fin);
+ if (file_size == UINT64_MAX)
{
- fputws(L"Error: Failed to open output file!\n\n", stderr);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
- }
-
- struct _stati64 stat;
- if (_fstati64(_fileno(fin), &stat) != 0)
- {
- fputws(L"I/O error: Failed to determine size of input file!\n\n", stderr);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
- if (stat.st_size < 12LL)
+ if (file_size < 16LL)
{
fputws(L"Error: Input file is too small!\n\n", stderr);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
- const int64_t limit = stat.st_size - sizeof(uint64_t);
-
uint64_t seed;
if (fread(&seed, sizeof(uint64_t), 1U, fin) < 1U)
{
- fputws(L"I/O error: Failed to read encrypted data!\n\n", stderr);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ fputws(L"I/O error: Failed to read seed value!\n\n", stderr);
+ goto clean_up;
}
- const mcrypt_t ctx = mcrypt_init(seed, passphrase_utf8);
+ ctx = mcrypt_alloc(seed, passphrase_utf8);
if (!ctx)
{
fputws(L"MCrypt error: Failed to initialize decryption!\n\n", stderr);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
fputws(L"Decrypting, please be patient... ", stderr);
int64_t bytes_read = sizeof(uint64_t);
uint8_t buffer[1024U];
- while ((!feof(fin)) && (bytes_read < limit))
+ const int64_t read_limit = file_size - sizeof(uint64_t);
+ while ((!feof(fin)) && (bytes_read < read_limit))
{
- const int64_t bytes_remaining = limit - bytes_read;
+ const int64_t bytes_remaining = read_limit - bytes_read;
const size_t read_len = (bytes_remaining < 1024U) ? ((size_t)bytes_remaining) : 1024U;
const size_t count = fread(buffer, sizeof(uint8_t), read_len, fin);
if (ferror(fin))
{
fputws(L"failed!\n\nI/O error: Failed to read encrypted data!\n\n", stderr);
- mcrypt_free(ctx);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
if (count > 0U)
{
if (mcrypt_dec_process_inplace(ctx, buffer, count) != 0)
{
fputws(L"failed!\n\nMCrypt error: Failed to decrypt data!\n\n", stderr);
- mcrypt_free(ctx);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
for (size_t i = 0U; i < count; ++i)
{
if (fwrite(buffer, sizeof(uint8_t), count, fout) < count)
{
fputws(L"failed!\n\nI/O error: Failed to write decrypted data!\n\n", stderr);
- mcrypt_free(ctx);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
}
}
crc_actual ^= ~0U;
- if (bytes_read < limit)
+ if (bytes_read < read_limit)
{
fputws(L"failed!\n\nI/O error: Input file could not be fully read!\n\n", stderr);
- mcrypt_free(ctx);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
uint64_t crc_expected;
if (fread(&crc_expected, sizeof(uint64_t), 1U, fin) < 1U)
{
fputws(L"failed!\n\nI/O error: Failed to read CRC checksum!\n\n", stderr);
- mcrypt_free(ctx);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 1;
+ goto clean_up;
}
if (crc_actual != crc_expected)
{
fwprintf(stderr, L"failed!\n\nCRC error: Checksum mismatch detected! [0x%016llX vs. 0x%016llX]\n\nWrong passphrase?\n\n", crc_actual, crc_expected);
+ goto clean_up;
+ }
+
+ result = 0;
+
+ fputws(L"done.\n\nCRC checksum is correct.\n\n", stderr);
+ fflush(stderr);
+
+clean_up:
+
+ if (ctx)
+ {
mcrypt_free(ctx);
+ }
+
+ if (fout)
+ {
fclose(fout);
+ }
+
+ if (fin)
+ {
fclose(fin);
- free(passphrase_utf8);
- return 1;
}
- fputws(L"done.\n\nCRC checksum is correct.\n\n", stderr);
+ if (passphrase_utf8)
+ {
+ erase(passphrase_utf8, strlen(passphrase_utf8));
+ free(passphrase_utf8);
+ }
- mcrypt_free(ctx);
- fclose(fout);
- fclose(fin);
- free(passphrase_utf8);
- return 0;
+ return result;
}
int wmain(int argc, wchar_t* argv[])
int result = -1;
const clock_t clk_start = clock();
- if ((argc > 4) && (_wcsicmp(argv[1U], L"--decrypt") == 0))
+ if ((argc > 4) && (!_wcsicmp(argv[1U], L"--decrypt")))
{
result = decrypt(argv[2U], argv[3U], argv[4U]);
+ erase(argv[2U], wcslen(argv[2U]) * sizeof(wchar_t));
}
else
{
result = encrypt(argv[1U], argv[2U], argv[3U]);
+ erase(argv[1U], wcslen(argv[1U]) * sizeof(wchar_t));
}
+ fputws(L"--------\n\n", stderr);
+ fflush(stderr);
+
const clock_t clk_end = clock();
- fwprintf(stderr, L"--------\n\nOperation completed after %.1f seconds.\n\n", ((double)(clk_end - clk_start)) / ((double)CLOCKS_PER_SEC));
+ fwprintf(stderr, L"Operation completed after %.1f seconds.\n\n", (clk_end - clk_start) / ((double)CLOCKS_PER_SEC));
}