Slightly improved key derivation function + allow to read passphrase from environment.
This commit is contained in:
parent
dcd7153973
commit
3683d2c450
@ -16,6 +16,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#define BUFF_SIZE 4096U
|
#define BUFF_SIZE 4096U
|
||||||
|
static const CHR *const ENVV_PASSWD_NAME = T("MCRYPT_PASSWD");
|
||||||
static volatile int g_interrupted = 0;
|
static volatile int g_interrupted = 0;
|
||||||
|
|
||||||
static char* read_passphrase(const CHR* const file_name)
|
static char* read_passphrase(const CHR* const file_name)
|
||||||
@ -112,32 +113,34 @@ static int encrypt(const char* const passphrase, const CHR* const input_path, co
|
|||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FPUTS(T("Encrypting file contents, please be patient... "), stderr);
|
||||||
|
|
||||||
uint64_t seed;
|
uint64_t seed;
|
||||||
if (mcrypt_generate_seed(&seed) != 0)
|
if (mcrypt_generate_seed(&seed) != MCRYPT_SUCCESS)
|
||||||
{
|
{
|
||||||
FPUTS(T("MCrypt error: Failed to generate seed!\n\n"), stderr);
|
FPUTS(T("\n\nMCrypt error: Failed to generate seed!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fwrite(&seed, sizeof(uint64_t), 1U, file_out) < 1U)
|
if (fwrite(&seed, sizeof(uint64_t), 1U, file_out) < 1U)
|
||||||
{
|
{
|
||||||
FPUTS(T("I/O error: Failed to write seed value!\n\n"), stderr);
|
FPUTS(T("\n\nI/O error: Failed to write seed value!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = mcrypt_alloc(seed, passphrase);
|
ctx = mcrypt_alloc(seed, (const uint8_t*)passphrase, strlen(passphrase));
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
{
|
{
|
||||||
FPUTS(T("MCrypt error: Failed to initialize encryption!\n\n"), stderr);
|
FPUTS(T("\n\nMCrypt error: Failed to initialize encryption!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
FPRINTF(stderr, T("Encrypting file contents, please be patient... %5.1f%%"), 0.0);
|
|
||||||
|
|
||||||
clock_t clk_now, clk_update = clock();
|
clock_t clk_now, clk_update = clock();
|
||||||
uint64_t crc_actual = CRC_INITIALIZER, bytes_read = sizeof(uint64_t);
|
uint64_t crc_actual = CRC_INITIALIZER, bytes_read = sizeof(uint64_t);
|
||||||
uint8_t buffer[BUFF_SIZE];
|
uint8_t buffer[BUFF_SIZE];
|
||||||
|
|
||||||
|
FPRINTF(stderr, T("%5.1f%% "), 0.0);
|
||||||
|
|
||||||
while (bytes_read < file_size)
|
while (bytes_read < file_size)
|
||||||
{
|
{
|
||||||
const uint64_t bytes_remaining = file_size - bytes_read;
|
const uint64_t bytes_remaining = file_size - bytes_read;
|
||||||
@ -147,7 +150,7 @@ static int encrypt(const char* const passphrase, const CHR* const input_path, co
|
|||||||
{
|
{
|
||||||
crc_actual = crc64_update(crc_actual, buffer, count);
|
crc_actual = crc64_update(crc_actual, buffer, count);
|
||||||
bytes_read += count;
|
bytes_read += count;
|
||||||
if (mcrypt_encrypt_inplace(ctx, buffer, count) != 0)
|
if (mcrypt_encrypt_inplace(ctx, buffer, count) != MCRYPT_SUCCESS)
|
||||||
{
|
{
|
||||||
FPUTS(T("\n\nMCrypt error: Failed to encrypt data!\n\n"), stderr);
|
FPUTS(T("\n\nMCrypt error: Failed to encrypt data!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
@ -164,7 +167,7 @@ static int encrypt(const char* const passphrase, const CHR* const input_path, co
|
|||||||
}
|
}
|
||||||
if ((clk_now = clock()) - clk_update > CLOCKS_PER_SEC)
|
if ((clk_now = clock()) - clk_update > CLOCKS_PER_SEC)
|
||||||
{
|
{
|
||||||
FPRINTF(stderr, T("\b\b\b\b\b\b%5.1f%%"), (bytes_read / ((double)file_size)) * 100.0);
|
FPRINTF(stderr, T("\b\b\b\b\b\b\b%5.1f%% "), (bytes_read / ((double)file_size)) * 100.0);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
clk_update = clk_now;
|
clk_update = clk_now;
|
||||||
}
|
}
|
||||||
@ -244,27 +247,29 @@ static int decrypt(const char* const passphrase, const CHR* const input_path, co
|
|||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FPUTS(T("Decrypting file contents, please be patient... "), stderr);
|
||||||
|
|
||||||
uint64_t seed;
|
uint64_t seed;
|
||||||
if (fread(&seed, sizeof(uint64_t), 1U, file_in) < 1U)
|
if (fread(&seed, sizeof(uint64_t), 1U, file_in) < 1U)
|
||||||
{
|
{
|
||||||
FPUTS(T("I/O error: Failed to read seed value!\n\n"), stderr);
|
FPUTS(T("\n\nI/O error: Failed to read seed value!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = mcrypt_alloc(seed, passphrase);
|
ctx = mcrypt_alloc(seed, (const uint8_t*)passphrase, strlen(passphrase));
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
{
|
{
|
||||||
FPUTS(T("MCrypt error: Failed to initialize decryption!\n\n"), stderr);
|
FPUTS(T("\n\nMCrypt error: Failed to initialize decryption!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
FPRINTF(stderr, T("Decrypting file contents, please be patient... %5.1f%%"), 0.0);
|
|
||||||
|
|
||||||
clock_t clk_now, clk_update = clock();
|
clock_t clk_now, clk_update = clock();
|
||||||
uint64_t crc_actual = CRC_INITIALIZER, bytes_read = sizeof(uint64_t);
|
uint64_t crc_actual = CRC_INITIALIZER, bytes_read = sizeof(uint64_t);
|
||||||
uint8_t buffer[BUFF_SIZE];
|
uint8_t buffer[BUFF_SIZE];
|
||||||
const uint64_t read_limit = file_size - sizeof(uint64_t);
|
const uint64_t read_limit = file_size - sizeof(uint64_t);
|
||||||
|
|
||||||
|
FPRINTF(stderr, T("%5.1f%% "), 0.0);
|
||||||
|
|
||||||
while (bytes_read < read_limit)
|
while (bytes_read < read_limit)
|
||||||
{
|
{
|
||||||
const uint64_t bytes_remaining = read_limit - bytes_read;
|
const uint64_t bytes_remaining = read_limit - bytes_read;
|
||||||
@ -273,7 +278,7 @@ static int decrypt(const char* const passphrase, const CHR* const input_path, co
|
|||||||
if (count > 0U)
|
if (count > 0U)
|
||||||
{
|
{
|
||||||
bytes_read += count;
|
bytes_read += count;
|
||||||
if (mcrypt_decrypt_inplace(ctx, buffer, count) != 0)
|
if (mcrypt_decrypt_inplace(ctx, buffer, count) != MCRYPT_SUCCESS)
|
||||||
{
|
{
|
||||||
FPUTS(T("\n\nMCrypt error: Failed to decrypt data!\n\n"), stderr);
|
FPUTS(T("\n\nMCrypt error: Failed to decrypt data!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
@ -291,7 +296,7 @@ static int decrypt(const char* const passphrase, const CHR* const input_path, co
|
|||||||
}
|
}
|
||||||
if ((clk_now = clock()) - clk_update > CLOCKS_PER_SEC)
|
if ((clk_now = clock()) - clk_update > CLOCKS_PER_SEC)
|
||||||
{
|
{
|
||||||
FPRINTF(stderr, T("\b\b\b\b\b\b%5.1f%%"), (bytes_read / ((double)read_limit)) * 100.0);
|
FPRINTF(stderr, T("\b\b\b\b\b\b\b%5.1f%% "), (bytes_read / ((double)read_limit)) * 100.0);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
clk_update = clk_now;
|
clk_update = clk_now;
|
||||||
}
|
}
|
||||||
@ -358,14 +363,14 @@ clean_up:
|
|||||||
|
|
||||||
static int run_test(const char *const message)
|
static int run_test(const char *const message)
|
||||||
{
|
{
|
||||||
static const char* const passphrase = "OrpheanBeh0lderScryDoubt!";
|
static const char* const passphrase = "OrpheanBeh0lderScry!Doubt";
|
||||||
|
|
||||||
const size_t length = strlen(message) + 1U;
|
const size_t length = strlen(message) + 1U;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
mcrypt_t ctx = MCRYPT_NULL;
|
mcrypt_t ctx = MCRYPT_NULL;
|
||||||
|
|
||||||
uint64_t seed;
|
uint64_t seed;
|
||||||
if (mcrypt_generate_seed(&seed) != 0)
|
if (mcrypt_generate_seed(&seed) != MCRYPT_SUCCESS)
|
||||||
{
|
{
|
||||||
FPUTS(T("\n\nWhoops: Failed to generate seed!\n\n"), stderr);
|
FPUTS(T("\n\nWhoops: Failed to generate seed!\n\n"), stderr);
|
||||||
return 1;
|
return 1;
|
||||||
@ -378,14 +383,14 @@ static int run_test(const char *const message)
|
|||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = mcrypt_alloc(seed, passphrase);
|
ctx = mcrypt_alloc(seed, (const uint8_t*)passphrase, strlen(passphrase));
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
{
|
{
|
||||||
FPUTS(T("\n\nnWhoops: Failed to initialize encoder!\n\n"), stderr);
|
FPUTS(T("\n\nnWhoops: Failed to initialize encoder!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mcrypt_encrypt_inplace(ctx, (uint8_t*)text_temp, length) != 0)
|
if (mcrypt_encrypt_inplace(ctx, (uint8_t*)text_temp, length) != MCRYPT_SUCCESS)
|
||||||
{
|
{
|
||||||
FPUTS(T("\n\nWhoops: Failed to encrypt the message!\n\n"), stderr);
|
FPUTS(T("\n\nWhoops: Failed to encrypt the message!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
@ -397,13 +402,13 @@ static int run_test(const char *const message)
|
|||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mcrypt_reset(ctx, seed, passphrase) != 0)
|
if (mcrypt_reset(ctx, seed, (const uint8_t*)passphrase, strlen(passphrase)) != MCRYPT_SUCCESS)
|
||||||
{
|
{
|
||||||
FPUTS(T("\n\nWhoops: Failed to initialize decoder!\n\n"), stderr);
|
FPUTS(T("\n\nWhoops: Failed to initialize decoder!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mcrypt_decrypt_inplace(ctx, (uint8_t*)text_temp, length) != 0)
|
if (mcrypt_decrypt_inplace(ctx, (uint8_t*)text_temp, length) != MCRYPT_SUCCESS)
|
||||||
{
|
{
|
||||||
FPUTS(T("\n\nWhoops: Failed to decrypt the message!\n\n"), stderr);
|
FPUTS(T("\n\nWhoops: Failed to decrypt the message!\n\n"), stderr);
|
||||||
goto clean_up;
|
goto clean_up;
|
||||||
@ -450,6 +455,11 @@ static int self_test(void)
|
|||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (g_interrupted)
|
||||||
|
{
|
||||||
|
FPUTS(T("\n\nProcess interrupted!\n\n"), stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,15 +490,20 @@ int MAIN(int argc, CHR* argv[])
|
|||||||
if ((!STRICMP(argv[1U], T("-h"))) || (!STRICMP(argv[1U], T("/?"))) || (!STRICMP(argv[1U], T("--help"))))
|
if ((!STRICMP(argv[1U], T("-h"))) || (!STRICMP(argv[1U], T("/?"))) || (!STRICMP(argv[1U], T("--help"))))
|
||||||
{
|
{
|
||||||
const CHR* const program = get_file_name(argv[0U]);
|
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);
|
||||||
FPUTS(T("--------------------------------------------------------------------\n\n"), stderr);
|
FPUTS(T("====================================================================\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"), program);
|
FPRINTF(stderr, T(" %") T(PRISTR) T(" --encrypt [[@][:]<passphrase>] <input.txt> <output.enc>\n"), program);
|
||||||
FPRINTF(stderr, T(" %") T(PRISTR) T(" --decrypt [@]<passphrase> <input.enc> <output.txt>\n\n"), program);
|
FPRINTF(stderr, T(" %") T(PRISTR) T(" --decrypt [[@][:]<passphrase>] <input.enc> <output.txt>\n\n"), program);
|
||||||
FPUTS(T("Note: If <passphrase> is prefixed with an '@' symbol, then it specifies the\n"), stderr);
|
FPUTS(T("Notes:\n"), stderr);
|
||||||
FPUTS(T("file to read the passphrase from. Only the first line in that file is used!\n\n"), stderr);
|
FPUTS(T("- If <passphrase> is prefixed with a '@' character, then it specifies the file\n"), stderr);
|
||||||
|
FPUTS(T(" to read the passphrase from; only the first line in that file is used!\n"), stderr);
|
||||||
|
FPUTS(T("- If <passphrase> is prefixed with a ':' character, then the leading character\n"), stderr);
|
||||||
|
FPUTS(T(" is skipped and the remainder of the argument is used as passphrase.\n"), stderr);
|
||||||
|
FPUTS(T("- If the argument <passphrase> is *not* present, then the environment variable\n"), stderr);
|
||||||
|
FPRINTF(stderr, T(" \"%") T(PRISTR) T("\" must be set and it specifies the passphrase to be used.\n\n"), ENVV_PASSWD_NAME);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((!STRICMP(argv[1U], T("-t"))) || (!STRICMP(argv[1U], T("--self-test"))))
|
if ((!STRICMP(argv[1U], T("-t"))) || (!STRICMP(argv[1U], T("--self-test"))))
|
||||||
@ -497,18 +512,23 @@ int MAIN(int argc, CHR* argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc < 5)
|
if (argc < 4)
|
||||||
{
|
{
|
||||||
const CHR* const program = get_file_name(argv[0U]);
|
const CHR* const program = get_file_name(argv[0U]);
|
||||||
FPRINTF(stderr, T("Error: Nothing to do. Please type '%") T(PRISTR) T(" --help' for details!\n\n"), program);
|
FPRINTF(stderr, T("Error: Nothing to do. Please type '%") T(PRISTR) T(" --help' for details!\n\n"), program);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else if (argc > 5)
|
||||||
const CHR *const command = argv[1U], *const passphrase = argv[2U], *const input_file = argv[3U], *const output_file = argv[4U];
|
|
||||||
|
|
||||||
if ((!passphrase[0U]) || ((passphrase[0U] == T('@')) && (!passphrase[1U])))
|
|
||||||
{
|
{
|
||||||
FPUTS(T("Error: The passphrase or passphrase file must not be empty!\n\n"), stderr);
|
FPUTS(T("Warning: Excess command-line argument is ignored!\n\n"), stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CHR *const command = argv[1U], *const passphrase = (argc > 4) ? argv[2U] : GETENV(ENVV_PASSWD_NAME);
|
||||||
|
const CHR *const input_file = argv[(argc > 4) ? 3U : 2U], *const output_file = argv[(argc > 4) ? 4U : 3U];
|
||||||
|
|
||||||
|
if ((!passphrase) || (!passphrase[0U]) || (((passphrase[0U] == T('@')) || (passphrase[0U] == T(':'))) && (!passphrase[1U])))
|
||||||
|
{
|
||||||
|
FPUTS(T("Error: The passphrase (file name) must not be empty!\n\n"), stderr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,7 +538,7 @@ int MAIN(int argc, CHR* argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *const passphrase_buffer = (passphrase[0U] == T('@')) ? read_passphrase(passphrase + 1U) : CHR_to_utf8(passphrase);
|
char *const passphrase_buffer = (passphrase[0U] == T('@')) ? read_passphrase(passphrase + 1U) : CHR_to_utf8((passphrase[0U] == T(':')) ? (passphrase + 1U) : passphrase);
|
||||||
if (!passphrase_buffer)
|
if (!passphrase_buffer)
|
||||||
{
|
{
|
||||||
FPUTS(T("Error: Failed to read the passphrase file!\n\n"), stderr);
|
FPUTS(T("Error: Failed to read the passphrase file!\n\n"), stderr);
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#define MAIN wmain
|
#define MAIN wmain
|
||||||
#define CHR wchar_t
|
#define CHR wchar_t
|
||||||
#define _T(X) L##X
|
#define _T(X) L##X
|
||||||
|
#define GETENV(X) _wgetenv((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 STRRCHR(X,Y) wcsrchr((X),(Y))
|
||||||
@ -72,6 +73,7 @@
|
|||||||
#define MAIN main
|
#define MAIN main
|
||||||
#define CHR char
|
#define CHR char
|
||||||
#define _T(X) X
|
#define _T(X) X
|
||||||
|
#define GETENV(X) getenv((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 STRRCHR(X,Y) strrchr((X),(Y))
|
||||||
|
@ -16,7 +16,13 @@ extern const char* const LIBMCRYPT_BUILDNO;
|
|||||||
* Opaque handle to internal state
|
* Opaque handle to internal state
|
||||||
*/
|
*/
|
||||||
typedef uintptr_t mcrypt_t;
|
typedef uintptr_t mcrypt_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constants
|
||||||
|
*/
|
||||||
#define MCRYPT_NULL ((mcrypt_t)NULL)
|
#define MCRYPT_NULL ((mcrypt_t)NULL)
|
||||||
|
#define MCRYPT_SUCCESS 0
|
||||||
|
#define MCRYPT_FAILURE (-1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Seed generator
|
* Seed generator
|
||||||
@ -26,20 +32,20 @@ int mcrypt_generate_seed(uint64_t* const seed);
|
|||||||
/*
|
/*
|
||||||
* Allocate, reset or free state
|
* Allocate, reset or free state
|
||||||
*/
|
*/
|
||||||
mcrypt_t mcrypt_alloc(const uint64_t salt, const char* const passphrase);
|
mcrypt_t mcrypt_alloc(const uint64_t salt, const uint8_t *const passwd, const size_t passwd_len);
|
||||||
int mcrypt_reset(const mcrypt_t context, const uint64_t salt, const char* const passphrase);
|
int mcrypt_reset(const mcrypt_t context, const uint64_t salt, const uint8_t *const passwd, const size_t passwd_len);
|
||||||
void mcrypt_free(const mcrypt_t context);
|
void mcrypt_free(const mcrypt_t context);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Encryption routines
|
* Encryption routines
|
||||||
*/
|
*/
|
||||||
int mcrypt_encrypt(const mcrypt_t context, const uint8_t* const input, uint8_t* const output, size_t length);
|
int mcrypt_encrypt(const mcrypt_t context, const uint8_t *const input, uint8_t* const output, size_t length);
|
||||||
int mcrypt_encrypt_inplace(const mcrypt_t context, uint8_t* const buffer, size_t length);
|
int mcrypt_encrypt_inplace(const mcrypt_t context, uint8_t *const buffer, size_t length);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decryption routines
|
* Decryption routines
|
||||||
*/
|
*/
|
||||||
int mcrypt_decrypt(const mcrypt_t context, const uint8_t* const input, uint8_t* const output, size_t length);
|
int mcrypt_decrypt(const mcrypt_t context, const uint8_t *const input, uint8_t *const output, size_t length);
|
||||||
int mcrypt_decrypt_inplace(const mcrypt_t context, uint8_t* const buffer, size_t length);
|
int mcrypt_decrypt_inplace(const mcrypt_t context, uint8_t* const buffer, size_t length);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -23,6 +23,12 @@
|
|||||||
const char* const LIBMCRYPT_VERSION = "1.0.0";
|
const char* const LIBMCRYPT_VERSION = "1.0.0";
|
||||||
const char* const LIBMCRYPT_BUILDNO = __DATE__", "__TIME__;
|
const char* const LIBMCRYPT_BUILDNO = __DATE__", "__TIME__;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint64_t a, b;
|
||||||
|
}
|
||||||
|
key_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t wheel_fwd[256U][256U];
|
uint8_t wheel_fwd[256U][256U];
|
||||||
@ -46,7 +52,7 @@ rand_state_t;
|
|||||||
// Hash function
|
// Hash function
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
static void hash_update(uint64_t* const h, const uint8_t* const data, const size_t data_len)
|
static FORCE_INLINE void hash_update(uint64_t *const h, const uint8_t* const data, const size_t data_len)
|
||||||
{
|
{
|
||||||
for (size_t i = 0U; i < data_len; ++i)
|
for (size_t i = 0U; i < data_len; ++i)
|
||||||
{
|
{
|
||||||
@ -64,20 +70,39 @@ static uint64_t hash_code(const uint64_t salt, const uint16_t pepper, const uint
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// Key derivation
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
static FORCE_INLINE uint64_t keygen_loop(uint64_t value, const uint16_t pepper, const uint8_t* const passwd, const size_t passwd_len)
|
||||||
|
{
|
||||||
|
for (size_t i = 0U; i < 99971U; ++i)
|
||||||
|
{
|
||||||
|
value = hash_code(value, pepper, passwd, passwd_len);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void generate_key(key_t *const key, const uint64_t salt, const uint16_t pepper, const uint8_t* const passwd, const size_t passwd_len)
|
||||||
|
{
|
||||||
|
key->a = keygen_loop(salt, pepper & 0x7FFF, passwd, passwd_len);
|
||||||
|
key->b = keygen_loop(salt, pepper | 0x8000, passwd, passwd_len);
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// PRNG
|
// PRNG
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
static void random_init(rand_state_t* const state, const uint64_t seed_0, const uint64_t seed_1)
|
static void random_init(rand_state_t* const state, const uint64_t seed_0, const uint64_t seed_1)
|
||||||
{
|
{
|
||||||
state->counter = 0U;
|
mcrypt_bzero(state, sizeof(rand_state_t));
|
||||||
state->a = (uint32_t)(seed_0 & 0xFFFFFFFF);
|
state->a = (uint32_t)( seed_0 & 0xFFFFFFFF);
|
||||||
state->b = (uint32_t)((seed_0 >> 32) & 0xFFFFFFFF);
|
state->b = (uint32_t)((seed_0 >> 32) & 0xFFFFFFFF);
|
||||||
state->c = (uint32_t)(seed_1 & 0xFFFFFFFF);
|
state->c = (uint32_t)( seed_1 & 0xFFFFFFFF);
|
||||||
state->d = (uint32_t)((seed_1 >> 32) & 0xFFFFFFFF);
|
state->d = (uint32_t)((seed_1 >> 32) & 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t random_next(rand_state_t* const state)
|
static uint32_t random_next(rand_state_t *const state)
|
||||||
{
|
{
|
||||||
uint32_t t = state->d;
|
uint32_t t = state->d;
|
||||||
const uint32_t s = state->a;
|
const uint32_t s = state->a;
|
||||||
@ -91,28 +116,31 @@ static uint32_t random_next(rand_state_t* const state)
|
|||||||
return t + (state->counter += 362437U);
|
return t + (state->counter += 362437U);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void random_seed(rand_state_t* const state, const uint64_t salt, const uint16_t pepper, const uint8_t* const key, const size_t key_len)
|
static void random_seed(rand_state_t* const state, const uint64_t salt, const uint16_t pepper, const uint8_t *const passwd, const size_t passwd_len)
|
||||||
{
|
{
|
||||||
const uint64_t hash_code_0 = hash_code(salt, pepper & 0x7FFF, key, key_len);
|
key_t key;
|
||||||
const uint64_t hash_code_1 = hash_code(salt, pepper | 0x8000, key, key_len);
|
generate_key(&key, salt, pepper, passwd, passwd_len);
|
||||||
random_init(state, hash_code_0, hash_code_1);
|
random_init(state, key.a, key.b);
|
||||||
for (size_t i = 0U; i < 13U; ++i)
|
for (size_t i = 0U; i < (salt % 97U) + 13U; ++i)
|
||||||
{
|
{
|
||||||
random_next(state);
|
random_next(state);
|
||||||
}
|
}
|
||||||
|
mcrypt_bzero(&key, sizeof(key_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Initialization
|
// Initialization
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
static void initialize_state(crypt_state_t* const crypt_state, const uint64_t salt, const uint8_t* const key, const size_t key_len)
|
static void initialize_state(crypt_state_t* const crypt_state, const uint64_t salt, const uint8_t* const passwd, const size_t passwd_len)
|
||||||
{
|
{
|
||||||
|
mcrypt_bzero(crypt_state, sizeof(crypt_state_t));
|
||||||
|
|
||||||
/* set up wheels and initial rotation */
|
/* set up wheels and initial rotation */
|
||||||
rand_state_t rand_state;
|
rand_state_t rand_state;
|
||||||
for (size_t r = 0U; r < 256U; ++r)
|
for (size_t r = 0U; r < 256U; ++r)
|
||||||
{
|
{
|
||||||
random_seed(&rand_state, salt, (uint16_t)r, key, key_len);
|
random_seed(&rand_state, salt, (uint16_t)r, passwd, passwd_len);
|
||||||
crypt_state->rotation_bwd[0U][255U - r] = crypt_state->rotation_fwd[0U][r] = (uint8_t)random_next(&rand_state);
|
crypt_state->rotation_bwd[0U][255U - r] = crypt_state->rotation_fwd[0U][r] = (uint8_t)random_next(&rand_state);
|
||||||
crypt_state->rotation_bwd[1U][255U - r] = crypt_state->rotation_fwd[1U][r] = 0U;
|
crypt_state->rotation_bwd[1U][255U - r] = crypt_state->rotation_fwd[1U][r] = 0U;
|
||||||
for (size_t i = 0U; i < 256U; ++i)
|
for (size_t i = 0U; i < 256U; ++i)
|
||||||
@ -132,7 +160,7 @@ static void initialize_state(crypt_state_t* const crypt_state, const uint64_t sa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set up stepping */
|
/* set up stepping */
|
||||||
random_seed(&rand_state, salt, 0x0100, key, key_len);
|
random_seed(&rand_state, salt, 256U, passwd, passwd_len);
|
||||||
for (size_t i = 0U; i < 256U; ++i)
|
for (size_t i = 0U; i < 256U; ++i)
|
||||||
{
|
{
|
||||||
const size_t j = random_next(&rand_state) % (i + 1U);
|
const size_t j = random_next(&rand_state) % (i + 1U);
|
||||||
@ -145,7 +173,6 @@ static void initialize_state(crypt_state_t* const crypt_state, const uint64_t sa
|
|||||||
crypt_state->step_bwd[j] = (uint8_t)(255U - i);
|
crypt_state->step_bwd[j] = (uint8_t)(255U - i);
|
||||||
}
|
}
|
||||||
|
|
||||||
crypt_state->counter = 0U;
|
|
||||||
mcrypt_bzero(&rand_state, sizeof(rand_state_t));
|
mcrypt_bzero(&rand_state, sizeof(rand_state_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,22 +223,22 @@ int mcrypt_generate_seed(uint64_t* const seed)
|
|||||||
{
|
{
|
||||||
if (!seed)
|
if (!seed)
|
||||||
{
|
{
|
||||||
return -1;
|
return MCRYPT_FAILURE;
|
||||||
}
|
}
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (mcrypt_random_bytes((uint8_t*)seed, sizeof(uint64_t)) != 0)
|
if (mcrypt_random_bytes((uint8_t*)seed, sizeof(uint64_t)) != 0)
|
||||||
{
|
{
|
||||||
return -1;
|
return MCRYPT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!(*seed));
|
while (!(*seed));
|
||||||
return 0;
|
return MCRYPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
mcrypt_t mcrypt_alloc(const uint64_t salt, const char* const passphrase)
|
mcrypt_t mcrypt_alloc(const uint64_t salt, const uint8_t *const passwd, const size_t passwd_len)
|
||||||
{
|
{
|
||||||
if (!passphrase)
|
if ((!passwd) || (passwd_len < 1U))
|
||||||
{
|
{
|
||||||
return ((mcrypt_t)NULL);
|
return ((mcrypt_t)NULL);
|
||||||
}
|
}
|
||||||
@ -220,19 +247,19 @@ mcrypt_t mcrypt_alloc(const uint64_t salt, const char* const passphrase)
|
|||||||
{
|
{
|
||||||
return ((mcrypt_t)NULL);
|
return ((mcrypt_t)NULL);
|
||||||
}
|
}
|
||||||
initialize_state(state, salt, (uint8_t*)passphrase, strlen(passphrase));
|
initialize_state(state, salt, passwd, passwd_len);
|
||||||
return ((mcrypt_t)state);
|
return ((mcrypt_t)state);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mcrypt_reset(const mcrypt_t context, const uint64_t salt, const char* const passphrase)
|
int mcrypt_reset(const mcrypt_t context, const uint64_t salt, const uint8_t *const passwd, const size_t passwd_len)
|
||||||
{
|
{
|
||||||
crypt_state_t* const state = (crypt_state_t*)context;
|
crypt_state_t* const state = (crypt_state_t*)context;
|
||||||
if ((!state) || (!passphrase))
|
if ((!state) || (!passwd) || (passwd_len < 1U))
|
||||||
{
|
{
|
||||||
return -1;
|
return MCRYPT_FAILURE;
|
||||||
}
|
}
|
||||||
initialize_state(state, salt, (uint8_t*)passphrase, strlen(passphrase));
|
initialize_state(state, salt, passwd, passwd_len);
|
||||||
return 0;
|
return MCRYPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mcrypt_encrypt(const mcrypt_t context, const uint8_t* const input, uint8_t* const output, size_t length)
|
int mcrypt_encrypt(const mcrypt_t context, const uint8_t* const input, uint8_t* const output, size_t length)
|
||||||
@ -240,13 +267,13 @@ int mcrypt_encrypt(const mcrypt_t context, const uint8_t* const input, uint8_t*
|
|||||||
crypt_state_t* const state = (crypt_state_t*)context;
|
crypt_state_t* const state = (crypt_state_t*)context;
|
||||||
if (!state)
|
if (!state)
|
||||||
{
|
{
|
||||||
return -1;
|
return MCRYPT_FAILURE;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < length; ++i)
|
for (size_t i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
output[i] = process_enc(state, input[i]);
|
output[i] = process_enc(state, input[i]);
|
||||||
}
|
}
|
||||||
return 0;
|
return MCRYPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mcrypt_encrypt_inplace(const mcrypt_t context, uint8_t* const buffer, size_t length)
|
int mcrypt_encrypt_inplace(const mcrypt_t context, uint8_t* const buffer, size_t length)
|
||||||
@ -254,13 +281,13 @@ int mcrypt_encrypt_inplace(const mcrypt_t context, uint8_t* const buffer, size_t
|
|||||||
crypt_state_t* const state = (crypt_state_t*)context;
|
crypt_state_t* const state = (crypt_state_t*)context;
|
||||||
if (!state)
|
if (!state)
|
||||||
{
|
{
|
||||||
return -1;
|
return MCRYPT_FAILURE;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < length; ++i)
|
for (size_t i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
buffer[i] = process_enc(state, buffer[i]);
|
buffer[i] = process_enc(state, buffer[i]);
|
||||||
}
|
}
|
||||||
return 0;
|
return MCRYPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -269,13 +296,13 @@ int mcrypt_decrypt(const mcrypt_t context, const uint8_t* const input, uint8_t*
|
|||||||
crypt_state_t* const state = (crypt_state_t*)context;
|
crypt_state_t* const state = (crypt_state_t*)context;
|
||||||
if (!state)
|
if (!state)
|
||||||
{
|
{
|
||||||
return -1;
|
return MCRYPT_FAILURE;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < length; ++i)
|
for (size_t i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
output[i] = process_dec(state, input[i]);
|
output[i] = process_dec(state, input[i]);
|
||||||
}
|
}
|
||||||
return 0;
|
return MCRYPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mcrypt_decrypt_inplace(const mcrypt_t context, uint8_t* const buffer, size_t length)
|
int mcrypt_decrypt_inplace(const mcrypt_t context, uint8_t* const buffer, size_t length)
|
||||||
@ -283,13 +310,13 @@ int mcrypt_decrypt_inplace(const mcrypt_t context, uint8_t* const buffer, size_t
|
|||||||
crypt_state_t* const state = (crypt_state_t*)context;
|
crypt_state_t* const state = (crypt_state_t*)context;
|
||||||
if (!state)
|
if (!state)
|
||||||
{
|
{
|
||||||
return -1;
|
return MCRYPT_FAILURE;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < length; ++i)
|
for (size_t i = 0; i < length; ++i)
|
||||||
{
|
{
|
||||||
buffer[i] = process_dec(state, buffer[i]);
|
buffer[i] = process_dec(state, buffer[i]);
|
||||||
}
|
}
|
||||||
return 0;
|
return MCRYPT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mcrypt_free(const mcrypt_t context)
|
void mcrypt_free(const mcrypt_t context)
|
||||||
|
Loading…
Reference in New Issue
Block a user