Implemented a simple padding scheme.

This commit is contained in:
LoRd_MuldeR 2020-12-01 02:24:35 +01:00
parent 99dec75db7
commit c530556e94
Signed by: mulder
GPG Key ID: 2B5913365F57E03F
2 changed files with 67 additions and 17 deletions

View File

@ -175,8 +175,8 @@ static void sigint_handler(const int sig)
static int encrypt(const char* const passphrase, const CHR* const input_path, const CHR* const output_path) static int encrypt(const char* const passphrase, const CHR* const input_path, const CHR* const output_path)
{ {
slunkcrypt_t ctx = SLUNKCRYPT_NULL; slunkcrypt_t ctx = SLUNKCRYPT_NULL;
FILE * file_in = NULL, * file_out = NULL; FILE *file_in = NULL, *file_out = NULL;
int result = EXIT_FAILURE; int result = EXIT_FAILURE, status;
if (open_files(&file_in, &file_out, input_path, output_path) != EXIT_SUCCESS) if (open_files(&file_in, &file_out, input_path, output_path) != EXIT_SUCCESS)
{ {
@ -235,8 +235,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;
const int status = slunkcrypt_encrypt_inplace(ctx, buffer, count); if ((status = slunkcrypt_encrypt_inplace(ctx, buffer, count)) != SLUNKCRYPT_SUCCESS)
if (status != SLUNKCRYPT_SUCCESS)
{ {
FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to encrypt data!\n\n"), stderr); FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to encrypt data!\n\n"), stderr);
goto clean_up; goto clean_up;
@ -265,16 +264,35 @@ static int encrypt(const char* const passphrase, const CHR* const input_path, co
goto clean_up; goto clean_up;
} }
if (bytes_read < file_size) if (bytes_read != file_size)
{ {
FPUTS(T("\n\nI/O error: Input file could not be fully read!\n\n"), stderr); FPUTS(T("\n\nI/O error: Input file could not be fully read!\n\n"), stderr);
goto clean_up; goto clean_up;
} }
const size_t padding = sizeof(uint64_t) - (file_size % 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_NIBBLE(buffer[padding - 1U], padding);
if ((status = slunkcrypt_encrypt_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;
}
crc_actual = swap_bytes_u64(crc64_finish(crc_actual)); crc_actual = swap_bytes_u64(crc64_finish(crc_actual));
const int status = slunkcrypt_encrypt_inplace(ctx, (uint8_t*)&crc_actual, sizeof(uint64_t)); if ((status = slunkcrypt_encrypt_inplace(ctx, (uint8_t*)&crc_actual, sizeof(uint64_t))) != SLUNKCRYPT_SUCCESS)
if (status != SLUNKCRYPT_SUCCESS)
{ {
FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to encrypt checksum!\n\n"), stderr); FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to encrypt checksum!\n\n"), stderr);
goto clean_up; goto clean_up;
@ -322,7 +340,7 @@ static int decrypt(const char* const passphrase, const CHR* const input_path, co
{ {
slunkcrypt_t ctx = SLUNKCRYPT_NULL; slunkcrypt_t ctx = SLUNKCRYPT_NULL;
FILE *file_in = NULL, *file_out = NULL; FILE *file_in = NULL, *file_out = NULL;
int result = EXIT_FAILURE; int result = EXIT_FAILURE, status;
if (open_files(&file_in, &file_out, input_path, output_path) != EXIT_SUCCESS) if (open_files(&file_in, &file_out, input_path, output_path) != EXIT_SUCCESS)
{ {
@ -335,7 +353,7 @@ static int decrypt(const char* const passphrase, const CHR* const input_path, co
FPUTS(T("I/O error: Failed to determine size of input file!\n\n"), stderr); FPUTS(T("I/O error: Failed to determine size of input file!\n\n"), stderr);
goto clean_up; goto clean_up;
} }
else if (file_size < 16U) else if (file_size < (3U * sizeof(uint64_t)))
{ {
FPUTS(T("Error: Input file is too small! Truncated?\n\n"), stderr); FPUTS(T("Error: Input file is too small! Truncated?\n\n"), stderr);
goto clean_up; goto clean_up;
@ -361,7 +379,7 @@ static int decrypt(const char* const passphrase, const CHR* const input_path, co
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[BUFFER_SIZE]; uint8_t buffer[BUFFER_SIZE];
const uint64_t read_limit = file_size - sizeof(uint64_t); const uint64_t read_limit = file_size - (2U * sizeof(uint64_t));
FPRINTF(stderr, T("%5.1f%% "), 0.0); FPRINTF(stderr, T("%5.1f%% "), 0.0);
fflush(stderr); fflush(stderr);
@ -374,8 +392,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;
const int status = slunkcrypt_decrypt_inplace(ctx, buffer, count); if ((status = slunkcrypt_decrypt_inplace(ctx, buffer, count)) != SLUNKCRYPT_SUCCESS)
if (status != SLUNKCRYPT_SUCCESS)
{ {
FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to decrypt data!\n\n"), stderr); FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to decrypt data!\n\n"), stderr);
goto clean_up; goto clean_up;
@ -405,12 +422,43 @@ static int decrypt(const char* const passphrase, const CHR* const input_path, co
goto clean_up; goto clean_up;
} }
if (bytes_read < read_limit) if (bytes_read != read_limit)
{ {
FPUTS(T("\n\nI/O error: Input file could not be fully read!\n\n"), stderr); FPUTS(T("\n\nI/O error: Input file could not be fully read!\n\n"), stderr);
goto clean_up; 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_decrypt_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_NIBBLE(buffer[sizeof(uint64_t) - 1U]);
if ((!padding) || (padding > sizeof(uint64_t)))
{
FPRINTF(stderr, T("\n\nPadding error: Erroneous padding length encountered! [0x%02X]\n\n"), (unsigned int)padding);
FPUTS(T("Wrong passphrase or corrupted file?\n\n"), stderr);
goto clean_up;
}
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;
}
crc_actual = crc64_update(crc_actual, buffer, count);
}
crc_actual = crc64_finish(crc_actual); crc_actual = crc64_finish(crc_actual);
uint64_t crc_expected; uint64_t crc_expected;
@ -420,8 +468,7 @@ static int decrypt(const char* const passphrase, const CHR* const input_path, co
goto clean_up; goto clean_up;
} }
const int status = slunkcrypt_decrypt_inplace(ctx, (uint8_t*)&crc_expected, sizeof(uint64_t)); if ((status = slunkcrypt_decrypt_inplace(ctx, (uint8_t*)&crc_expected, sizeof(uint64_t))) != SLUNKCRYPT_SUCCESS)
if (status != SLUNKCRYPT_SUCCESS)
{ {
FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to decrypt checksum!\n\n"), stderr); FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nSlunkCrypt error: Failed to decrypt checksum!\n\n"), stderr);
goto clean_up; goto clean_up;

View File

@ -18,4 +18,7 @@ char* CHR_to_utf8(const CHR *const input);
uint64_t get_file_size(FILE* const file); uint64_t get_file_size(FILE* const file);
const CHR *get_file_name(const CHR *path); const CHR *get_file_name(const CHR *path);
#define GET_NIBBLE(X) ((X) & 0x0F)
#define SET_NIBBLE(X, Y) do { X = ((X) & 0xF0) | ((Y) & 0x0F); } while(0)
#endif #endif