Make it possible to read the passphrase from a file.

This commit is contained in:
LoRd_MuldeR 2020-10-14 16:36:17 +02:00
parent 270c8b4ecd
commit a3fd6360e1
Signed by: mulder
GPG Key ID: 2B5913365F57E03F
4 changed files with 115 additions and 59 deletions

View File

@ -12,15 +12,59 @@
#include <time.h> #include <time.h>
#include <inttypes.h> #include <inttypes.h>
#include <ctype.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)
{ {
fputc('"', stderr); const size_t buff_size = 1024U;
for (size_t i = 0; i < length; ++i) char *const buffer = (char*) malloc(buff_size * sizeof(char));
if (!buffer)
{ {
fputc((text[i] >= 0x20) ? text[i] : '?', stderr); return NULL;
} }
fputs("\"\n\n", stderr); 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)
{
int flags[4U] = { 0, 0, 0, 0 };
while (*str)
{
const CHR c = *str++;
if (isalpha(c))
{
flags[isupper(c) ? 0U : 1U] = 1;
}
else
{
flags[isdigit(c) ? 2U : 3U] = 1;
}
}
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) static int open_files(FILE** const fin, FILE** const fout, const CHR* const input, const CHR* const output)
@ -43,21 +87,6 @@ static int open_files(FILE** const fin, FILE** const fout, const CHR* const inpu
return 0; 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) static int encrypt(const char* const passphrase, const CHR* const input, const CHR* const output)
{ {
mcrypt_t ctx = MCRYPT_NULL; mcrypt_t ctx = MCRYPT_NULL;
@ -136,6 +165,11 @@ static int encrypt(const char* const passphrase, const CHR* const input, const C
fflush(stderr); fflush(stderr);
clk_update = clk_now; clk_update = clk_now;
} }
if (g_interrupted)
{
FPUTS(T("\n\nProcess interrupted!\n\n"), stderr);
goto clean_up;
}
} }
crc_actual = crc64_finish(crc_actual); crc_actual = crc64_finish(crc_actual);
@ -254,6 +288,11 @@ static int decrypt(const char* const passphrase, const CHR* const input, const C
fflush(stderr); fflush(stderr);
clk_update = clk_now; clk_update = clk_now;
} }
if (g_interrupted)
{
FPUTS(T("\n\nProcess interrupted!\n\n"), stderr);
goto clean_up;
}
} }
crc_actual = crc64_finish(crc_actual); crc_actual = crc64_finish(crc_actual);
@ -392,9 +431,16 @@ clean_up:
return result; return result;
} }
static void sigint_handler(const int sig)
{
g_interrupted = 1;
signal(SIGINT, sigint_handler);
}
int MAIN(int argc, CHR* argv[]) int MAIN(int argc, CHR* argv[])
{ {
init_terminal(); 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("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); FPRINTF(stderr, T("Using libMCrypt v%") T(PRIstr) T(" [%") T(PRIstr) T("]\n\n"), LIBMCRYPT_VERSION, LIBMCRYPT_BUILDNO);
@ -407,6 +453,7 @@ int MAIN(int argc, CHR* argv[])
const int help_requested = (argc > 1) && ((!STRICMP(argv[1U], T("/?"))) || (!STRICMP(argv[1U], T("--help"))) || (!STRICMP(argv[1U], T("--version")))); 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) if ((argc < 5) || help_requested)
{ {
const CHR* const program = get_file_name(argv[0U]);
FPUTS(T("--------------------------------------------------------------------\n"), stderr); FPUTS(T("--------------------------------------------------------------------\n"), stderr);
FPUTS(T("This software has been released under the CC0 1.0 Universal license:\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("https://creativecommons.org/publicdomain/zero/1.0/legalcode\n"), stderr);
@ -416,28 +463,20 @@ int MAIN(int argc, CHR* argv[])
FPUTS(T("Error: Required argument is missing!\n\n"), stderr); FPUTS(T("Error: Required argument is missing!\n\n"), stderr);
} }
FPUTS(T("Usage:\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(" --encrypt [@]<passphrase> <input.dat> <output.enc>\n"), program);
FPRINTF(stderr, T(" %") T(PRISTR) T(" --decrypt <passphrase> <input.enc> <output.txt>\n\n"), argv[0U]); 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; 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]; 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; 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])) if ((!input_file[0U]) || (!output_file[0U]))
{ {
@ -445,23 +484,32 @@ int MAIN(int argc, CHR* argv[])
return 1; return 1;
} }
char* const passphrase_utf8 = CHR_to_utf8(passphrase); char *const passphrase_buffer = (passphrase[0U] == T('@')) ? read_passphrase(passphrase + 1U) : CHR_to_utf8(passphrase);
if (!passphrase_utf8) 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; 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(); const clock_t clk_start = clock();
int result = -1; int result = -1;
if (!STRICMP(command, T("--encrypt"))) 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"))) else if (!STRICMP(command, T("--decrypt")))
{ {
result = decrypt(passphrase_utf8, input_file, output_file); result = decrypt(passphrase_buffer, input_file, output_file);
} }
else else
{ {
@ -477,10 +525,10 @@ int MAIN(int argc, CHR* argv[])
exiting: exiting:
if (passphrase_utf8) if (passphrase_buffer)
{ {
mcrypt_bzero(passphrase_utf8, strlen(passphrase_utf8)); mcrypt_bzero(passphrase_buffer, strlen(passphrase_buffer));
free(passphrase_utf8); free(passphrase_buffer);
} }
mcrypt_bzero((CHR*)passphrase, STRLEN(passphrase) * sizeof(CHR)); mcrypt_bzero((CHR*)passphrase, STRLEN(passphrase) * sizeof(CHR));

View File

@ -55,16 +55,13 @@
#define _T(X) L##X #define _T(X) L##X
#define STRLEN(X) wcslen((X)) #define STRLEN(X) wcslen((X))
#define STRICMP(X,Y) _wcsicmp((X),(Y)) #define STRICMP(X,Y) _wcsicmp((X),(Y))
#define STRRCHR(X,Y) wcsrchr((X),(Y))
#define FPUTS(X,Y) fputws((X),(Y)) #define FPUTS(X,Y) fputws((X),(Y))
#define FPRINTF(X,Y,...) fwprintf((X),(Y),__VA_ARGS__) #define FPRINTF(X,Y,...) fwprintf((X),(Y),__VA_ARGS__)
#define FOPEN(X,Y) _wfsopen((X),(Y),_SH_SECURE) #define FOPEN(X,Y) _wfsopen((X),(Y),_SH_SECURE)
#define FILENO(X) _fileno((X)) #define FILENO(X) _fileno((X))
#define FSTAT64(X,Y) _fstati64((X),(Y)) #define FSTAT64(X,Y) _fstati64((X),(Y))
#define STAT64_T struct _stati64 #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__ #ifdef __MINGW32__
#define PRISTR "ls" #define PRISTR "ls"
#define PRIstr "hs" #define PRIstr "hs"
@ -80,16 +77,13 @@
#define _T(X) X #define _T(X) X
#define STRLEN(X) strlen((X)) #define STRLEN(X) strlen((X))
#define STRICMP(X,Y) strcasecmp((X),(Y)) #define STRICMP(X,Y) strcasecmp((X),(Y))
#define STRRCHR(X,Y) strrchr((X),(Y))
#define FPUTS(X,Y) fputs((X),(Y)) #define FPUTS(X,Y) fputs((X),(Y))
#define FPRINTF(X,Y,...) fprintf((X),(Y),__VA_ARGS__) #define FPRINTF(X,Y,...) fprintf((X),(Y),__VA_ARGS__)
#define FOPEN(X,Y) fopen((X),(Y)) #define FOPEN(X,Y) fopen((X),(Y))
#define FILENO(X) fileno((X)) #define FILENO(X) fileno((X))
#define FSTAT64(X,Y) fstat64((X),(Y)) #define FSTAT64(X,Y) fstat64((X),(Y))
#define STAT64_T struct stat64 #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 PRIstr "s" #define PRIstr "s"
#define PRIwcs "ls" #define PRIwcs "ls"

View File

@ -11,7 +11,6 @@
#endif #endif
#include "utils.h" #include "utils.h"
#include <mcrypt.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
@ -24,6 +23,14 @@
#define S_IFIFO _S_IFIFO #define S_IFIFO _S_IFIFO
#endif #endif
void init_terminal(void)
{
#ifdef _WIN32
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
_setmode(_fileno(stderr), _O_U8TEXT);
#endif
}
char* CHR_to_utf8(const CHR*const input) char* CHR_to_utf8(const CHR*const input)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -55,7 +62,7 @@ char* CHR_to_utf8(const CHR*const input)
#endif #endif
} }
uint64_t get_file_size(FILE *const file) uint64_t get_file_size(FILE* const file)
{ {
STAT64_T stat; STAT64_T stat;
if (FSTAT64(FILENO(file), &stat) != 0) if (FSTAT64(FILENO(file), &stat) != 0)
@ -70,10 +77,16 @@ uint64_t get_file_size(FILE *const file)
return 0U; return 0U;
} }
void init_terminal(void) const CHR* get_file_name(const CHR* path)
{ {
#ifdef _WIN32 const CHR* ptr;
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); while (ptr = STRRCHR(path, T('/')))
_setmode(_fileno(stderr), _O_U8TEXT); {
#endif path = ptr + 1U;
}
while (ptr = STRRCHR(path, T('\\')))
{
path = ptr + 1U;
}
return path;
} }

View File

@ -9,8 +9,9 @@
#include "platform.h" #include "platform.h"
#include <stdint.h> #include <stdint.h>
void init_terminal(void);
char* CHR_to_utf8(const CHR *const input); char* CHR_to_utf8(const CHR *const input);
uint64_t get_file_size(FILE* const file); uint64_t get_file_size(FILE* const file);
void init_terminal(void); const CHR *get_file_name(const CHR *path);
#endif #endif