#include <time.h>
#include <inttypes.h>
#include <ctype.h>
+#include <signal.h>
-static void print_string(const char *const text, const size_t length)
+static volatile int g_interrupted = 0;
+
+static char* read_passphrase(const CHR* const file_name)
+{
+ const size_t buff_size = 1024U;
+ char *const buffer = (char*) malloc(buff_size * sizeof(char));
+ if (!buffer)
+ {
+ return NULL;
+ }
+ FILE *const fin = FOPEN(file_name, T("rb"));
+ if (!fin)
+ {
+ return NULL;
+ }
+ do
+ {
+ if (!fgets(buffer, (int)buff_size, fin))
+ {
+ fclose(fin);
+ free(buffer);
+ return NULL;
+ }
+ size_t length = strlen(buffer);
+ while ((length > 0U) && ((buffer[length - 1U] == '\r') || (buffer[length - 1U] == '\n')))
+ {
+ buffer[--length] = '\0';
+ }
+ }
+ while (!buffer[0U]);
+ fclose(fin);
+ return buffer;
+}
+
+static int weak_passphrase(const char *str)
{
- fputc('"', stderr);
- for (size_t i = 0; i < length; ++i)
+ int flags[4U] = { 0, 0, 0, 0 };
+ while (*str)
{
- fputc((text[i] >= 0x20) ? text[i] : '?', stderr);
+ const CHR c = *str++;
+ if (isalpha(c))
+ {
+ flags[isupper(c) ? 0U : 1U] = 1;
+ }
+ else
+ {
+ flags[isdigit(c) ? 2U : 3U] = 1;
+ }
}
- fputs("\"\n\n", stderr);
+ const int strong = flags[0U] && flags[1U] && flags[2U] && flags[3U];
+ return !strong;
}
static int open_files(FILE** const fin, FILE** const fout, const CHR* const input, const CHR* const output)
return 0;
}
-static int weak_passphrase(const CHR *str)
-{
- int flags[4U] = { 0, 0, 0, 0 };
- while (*str)
- {
- const CHR c = *str++;
- if (ISUPPER(c)) flags[0U] = 1;
- else if (ISLOWER(c)) flags[1U] = 1;
- else if (ISDIGIT(c)) flags[2U] = 1;
- else if (ISGRAPH(c)) flags[3U] = 1;
- }
- const int strong = flags[0U] && flags[1U] && flags[2U] && flags[3U];
- return !strong;
-}
-
static int encrypt(const char* const passphrase, const CHR* const input, const CHR* const output)
{
mcrypt_t ctx = MCRYPT_NULL;
fflush(stderr);
clk_update = clk_now;
}
+ if (g_interrupted)
+ {
+ FPUTS(T("\n\nProcess interrupted!\n\n"), stderr);
+ goto clean_up;
+ }
}
crc_actual = crc64_finish(crc_actual);
fflush(stderr);
clk_update = clk_now;
}
+ if (g_interrupted)
+ {
+ FPUTS(T("\n\nProcess interrupted!\n\n"), stderr);
+ goto clean_up;
+ }
}
crc_actual = crc64_finish(crc_actual);
return result;
}
+static void sigint_handler(const int sig)
+{
+ g_interrupted = 1;
+ signal(SIGINT, sigint_handler);
+}
+
int MAIN(int argc, CHR* argv[])
{
init_terminal();
+ signal(SIGINT, sigint_handler);
FPRINTF(stderr, T("MCrypt Utility (%") T(PRIstr) T("-%") T(PRIstr) T("), by LoRd_MuldeR <MuldeR2@GMX.de>\n"), OS_TYPE, CPU_ARCH);
FPRINTF(stderr, T("Using libMCrypt v%") T(PRIstr) T(" [%") T(PRIstr) T("]\n\n"), LIBMCRYPT_VERSION, LIBMCRYPT_BUILDNO);
const int help_requested = (argc > 1) && ((!STRICMP(argv[1U], T("/?"))) || (!STRICMP(argv[1U], T("--help"))) || (!STRICMP(argv[1U], T("--version"))));
if ((argc < 5) || help_requested)
{
+ const CHR* const program = get_file_name(argv[0U]);
FPUTS(T("--------------------------------------------------------------------\n"), stderr);
FPUTS(T("This software has been released under the CC0 1.0 Universal license:\n"), stderr);
FPUTS(T("https://creativecommons.org/publicdomain/zero/1.0/legalcode\n"), stderr);
FPUTS(T("Error: Required argument is missing!\n\n"), stderr);
}
FPUTS(T("Usage:\n"), stderr);
- FPRINTF(stderr, T(" %") T(PRISTR) T(" --encrypt <passphrase> <input.txt> <output.enc>\n"), argv[0U]);
- FPRINTF(stderr, T(" %") T(PRISTR) T(" --decrypt <passphrase> <input.enc> <output.txt>\n\n"), argv[0U]);
+ FPRINTF(stderr, T(" %") T(PRISTR) T(" --encrypt [@]<passphrase> <input.dat> <output.enc>\n"), program);
+ FPRINTF(stderr, T(" %") T(PRISTR) T(" --decrypt [@]<passphrase> <input.enc> <output.dat>\n\n"), program);
+ FPUTS(T("Note: If <passphrase> starts with an '@' symbol, the remainder specifies the\n"), stderr);
+ FPUTS(T("file to read the passphrase from. Only the *first* line in the file is used!\n"), stderr);
return help_requested ? 0 : 1;
}
const CHR *const command = argv[1U], *const passphrase = argv[2U], *const input_file = argv[3U], *const output_file = argv[4U];
- if (!passphrase[0U])
+
+ if ((!passphrase[0U]) || ((passphrase[0U] == T('@')) && (!passphrase[1U])))
{
- FPUTS(T("Error: The passphrase must not be empty!\n\n"), stderr);
+ FPUTS(T("Error: The passphrase or passphrase file must not be empty!\n\n"), stderr);
return 1;
}
- else
- {
- if (STRLEN(passphrase) < 12U)
- {
- FPUTS(T("Warning: Using a *short* passphrase; a length of 12 characters or more is recommended!\n\n"), stderr);
- }
- if (weak_passphrase(passphrase))
- {
- FPUTS(T("Warning: Using a *weak* passphrase; a mix of upper-case letters, lower-case letters, digits and 'special' characters is recommended!\n\n"), stderr);
- }
- }
if ((!input_file[0U]) || (!output_file[0U]))
{
return 1;
}
- char* const passphrase_utf8 = CHR_to_utf8(passphrase);
- if (!passphrase_utf8)
+ char *const passphrase_buffer = (passphrase[0U] == T('@')) ? read_passphrase(passphrase + 1U) : CHR_to_utf8(passphrase);
+ if (!passphrase_buffer)
{
- FPUTS(T("Error: Failed to convert passphrase to the UTF-8 format!\n\n"), stderr);
+ FPUTS(T("Error: Failed to read the passphrase file!\n\n"), stderr);
return 1;
}
+ if (strlen(passphrase_buffer) < 12U)
+ {
+ FPUTS(T("Warning: Using a *short* passphrase; a length of 12 characters or more is recommended!\n\n"), stderr);
+ }
+ else if (weak_passphrase(passphrase_buffer))
+ {
+ FPUTS(T("Warning: Using a *weak* passphrase; a mix of upper-case letters, lower-case letters, digits and 'special' characters is recommended!\n\n"), stderr);
+ }
+
const clock_t clk_start = clock();
int result = -1;
if (!STRICMP(command, T("--encrypt")))
{
- result = encrypt(passphrase_utf8, input_file, output_file);
+ result = encrypt(passphrase_buffer, input_file, output_file);
}
else if (!STRICMP(command, T("--decrypt")))
{
- result = decrypt(passphrase_utf8, input_file, output_file);
+ result = decrypt(passphrase_buffer, input_file, output_file);
}
else
{
exiting:
- if (passphrase_utf8)
+ if (passphrase_buffer)
{
- mcrypt_bzero(passphrase_utf8, strlen(passphrase_utf8));
- free(passphrase_utf8);
+ mcrypt_bzero(passphrase_buffer, strlen(passphrase_buffer));
+ free(passphrase_buffer);
}
mcrypt_bzero((CHR*)passphrase, STRLEN(passphrase) * sizeof(CHR));
#define _T(X) L##X
#define STRLEN(X) wcslen((X))
#define STRICMP(X,Y) _wcsicmp((X),(Y))
+#define STRRCHR(X,Y) wcsrchr((X),(Y))
#define FPUTS(X,Y) fputws((X),(Y))
#define FPRINTF(X,Y,...) fwprintf((X),(Y),__VA_ARGS__)
#define FOPEN(X,Y) _wfsopen((X),(Y),_SH_SECURE)
#define FILENO(X) _fileno((X))
#define FSTAT64(X,Y) _fstati64((X),(Y))
#define STAT64_T struct _stati64
-#define ISUPPER(X) iswupper((X))
-#define ISLOWER(X) iswlower((X))
-#define ISDIGIT(X) iswdigit((X))
-#define ISGRAPH(X) iswgraph((X))
#ifdef __MINGW32__
#define PRISTR "ls"
#define PRIstr "hs"
#define _T(X) X
#define STRLEN(X) strlen((X))
#define STRICMP(X,Y) strcasecmp((X),(Y))
+#define STRRCHR(X,Y) strrchr((X),(Y))
#define FPUTS(X,Y) fputs((X),(Y))
#define FPRINTF(X,Y,...) fprintf((X),(Y),__VA_ARGS__)
#define FOPEN(X,Y) fopen((X),(Y))
#define FILENO(X) fileno((X))
#define FSTAT64(X,Y) fstat64((X),(Y))
#define STAT64_T struct stat64
-#define ISUPPER(X) isupper((X))
-#define ISLOWER(X) islower((X))
-#define ISDIGIT(X) isdigit((X))
-#define ISGRAPH(X) isgraph((X))
#define PRISTR "s"
#define PRIstr "s"
#define PRIwcs "ls"