2021-04-18 15:32:37 +02:00
|
|
|
/******************************************************************************/
|
|
|
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
|
|
|
/* This work has been released under the CC0 1.0 Universal license! */
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
/* Internal */
|
2022-09-20 21:52:23 +02:00
|
|
|
#include "selftest.h"
|
2021-04-18 15:32:37 +02:00
|
|
|
#include "utils.h"
|
2022-09-20 21:52:23 +02:00
|
|
|
#include "crypt.h"
|
2021-04-18 15:32:37 +02:00
|
|
|
#include "test_data.h"
|
|
|
|
#include "blake2.h"
|
|
|
|
|
2022-09-20 21:52:23 +02:00
|
|
|
/* Library */
|
|
|
|
#include <slunkcrypt.h>
|
|
|
|
|
2021-04-18 15:32:37 +02:00
|
|
|
/* CRT */
|
|
|
|
#include <time.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
// ==========================================================================
|
|
|
|
// Self-test routines
|
|
|
|
// ==========================================================================
|
|
|
|
|
2022-04-07 00:15:07 +02:00
|
|
|
static int run_testcase(const char* const message, const uint64_t nonce, const uint64_t checksum_message, const uint64_t checksum_expected, const slunkparam_t *const param)
|
2021-04-18 15:32:37 +02:00
|
|
|
{
|
|
|
|
static const char* const TEST_PASSPHRASE = "OrpheanBeh0lderScry!Doubt";
|
|
|
|
|
|
|
|
int status, result = EXIT_FAILURE;
|
|
|
|
const size_t length = strlen(message) + 1U;
|
|
|
|
slunkcrypt_t ctx = SLUNKCRYPT_NULL;
|
|
|
|
|
|
|
|
char* const text_temp = strdup(message);
|
|
|
|
if (!text_temp)
|
|
|
|
{
|
|
|
|
FPUTS(T("\n\nWhoops: Failed to allocate text buffer!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint64_t checksum_original = blake2s_compute((uint8_t*)text_temp, length);
|
|
|
|
if (checksum_original != checksum_message)
|
|
|
|
{
|
|
|
|
FPRINTF(stderr, T("\n\nWhoops: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_message, checksum_original);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
2022-04-07 00:15:07 +02:00
|
|
|
ctx = slunkcrypt_alloc_ext(nonce, (const uint8_t*)TEST_PASSPHRASE, strlen(TEST_PASSPHRASE), SLUNKCRYPT_ENCRYPT, param);
|
2021-04-18 15:32:37 +02:00
|
|
|
if (!ctx)
|
|
|
|
{
|
|
|
|
FPUTS(g_slunkcrypt_abort_flag ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to initialize encoder!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = slunkcrypt_inplace(ctx, (uint8_t*)text_temp, length);
|
|
|
|
if (status != SLUNKCRYPT_SUCCESS)
|
|
|
|
{
|
|
|
|
FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to encrypt the message!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strncmp(message, text_temp, length) == 0)
|
|
|
|
{
|
|
|
|
FPUTS(T("\n\nWhoops: Encrypted message equals the original message!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint64_t checksum_encrypted = blake2s_compute((uint8_t*)text_temp, length);
|
|
|
|
if (checksum_encrypted != checksum_expected)
|
|
|
|
{
|
|
|
|
FPRINTF(stderr, T("\n\nWhoops: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_expected, checksum_encrypted);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = slunkcrypt_reset(ctx, nonce, (const uint8_t*)TEST_PASSPHRASE, strlen(TEST_PASSPHRASE), SLUNKCRYPT_DECRYPT);
|
|
|
|
if (status != SLUNKCRYPT_SUCCESS)
|
|
|
|
{
|
|
|
|
FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to initialize decoder!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = slunkcrypt_inplace(ctx, (uint8_t*)text_temp, length);
|
|
|
|
if (status != SLUNKCRYPT_SUCCESS)
|
|
|
|
{
|
|
|
|
FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to decrypt the message!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp(message, text_temp, length * sizeof(char)) != 0)
|
|
|
|
{
|
|
|
|
FPUTS(T("\n\nWhoops: Decrypted message does *not* match the original message!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint64_t checksum_decrypted = blake2s_compute((uint8_t*)text_temp, length);
|
|
|
|
if (checksum_decrypted != checksum_original)
|
|
|
|
{
|
|
|
|
FPRINTF(stderr, T("\n\nWhoops: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_original, checksum_decrypted);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = EXIT_SUCCESS;
|
|
|
|
|
|
|
|
clean_up:
|
|
|
|
|
2022-04-02 17:27:48 +02:00
|
|
|
SLUNKCRYPT_SAFE_FREE(ctx);
|
2021-04-18 15:32:37 +02:00
|
|
|
|
|
|
|
if (text_temp)
|
|
|
|
{
|
|
|
|
slunkcrypt_bzero(text_temp, strlen(text_temp));
|
|
|
|
free(text_temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-04-07 00:15:07 +02:00
|
|
|
static int run_stresstest(const uint64_t nonce, const slunkparam_t *const param)
|
2022-04-02 17:27:48 +02:00
|
|
|
{
|
|
|
|
static const char* const TEST_PASSPHRASE = "OrpheanBeh0lderScry!Doubt";
|
|
|
|
static const size_t LENGTH = 134217689U, CHUNKZ_ENC = 8191U, CHUNKZ_DEC = 8179U;
|
|
|
|
|
|
|
|
int status, result = EXIT_FAILURE;
|
|
|
|
size_t offset, chunk_size;
|
|
|
|
slunkcrypt_t ctx = SLUNKCRYPT_NULL;
|
|
|
|
|
|
|
|
uint8_t* const buffer = (uint8_t*)malloc(LENGTH * sizeof(uint8_t));
|
|
|
|
if (!buffer)
|
|
|
|
{
|
|
|
|
FPUTS(T("\n\nWhoops: Failed to allocate message buffer!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slunkcrypt_random_bytes(buffer, LENGTH) != LENGTH)
|
|
|
|
{
|
|
|
|
FPUTS(T("\n\nWhoops: Failed to generate random message!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint64_t checksum_original = blake2s_compute(buffer, LENGTH);
|
|
|
|
|
2022-04-07 00:15:07 +02:00
|
|
|
ctx = slunkcrypt_alloc_ext(nonce, (const uint8_t*)TEST_PASSPHRASE, strlen(TEST_PASSPHRASE), SLUNKCRYPT_ENCRYPT, param);
|
2022-04-02 17:27:48 +02:00
|
|
|
if (!ctx)
|
|
|
|
{
|
|
|
|
FPUTS(g_slunkcrypt_abort_flag ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to initialize encoder!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (offset = 0U; offset < LENGTH; offset += chunk_size)
|
|
|
|
{
|
|
|
|
chunk_size = ((LENGTH - offset) > CHUNKZ_ENC) ? CHUNKZ_ENC : (LENGTH - offset);
|
|
|
|
status = slunkcrypt_inplace(ctx, buffer + offset, chunk_size);
|
|
|
|
if (status != SLUNKCRYPT_SUCCESS)
|
|
|
|
{
|
|
|
|
FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to encrypt the message!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
status = slunkcrypt_reset(ctx, nonce, (const uint8_t*)TEST_PASSPHRASE, strlen(TEST_PASSPHRASE), SLUNKCRYPT_DECRYPT);
|
|
|
|
if (status != SLUNKCRYPT_SUCCESS)
|
|
|
|
{
|
|
|
|
FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to initialize decoder!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (offset = 0U; offset < LENGTH; offset += chunk_size)
|
|
|
|
{
|
|
|
|
chunk_size = ((LENGTH - offset) > CHUNKZ_DEC) ? CHUNKZ_DEC : (LENGTH - offset);
|
|
|
|
status = slunkcrypt_inplace(ctx, buffer + offset, chunk_size);
|
|
|
|
if (status != SLUNKCRYPT_SUCCESS)
|
|
|
|
{
|
|
|
|
FPUTS((status == SLUNKCRYPT_ABORTED) ? T("\n\nProcess interrupted!\n\n") : T("\n\nWhoops: Failed to decrypt the message!\n\n"), stderr);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint64_t checksum_decrypted = blake2s_compute(buffer, LENGTH);
|
|
|
|
if (checksum_decrypted != checksum_original)
|
|
|
|
{
|
|
|
|
FPRINTF(stderr, T("\n\nWhoops: Checksum mismatch detected! [expected: 0x%016") T(PRIX64) T(", actual: 0x%016") T(PRIX64) T("]\n\n"), checksum_original, checksum_decrypted);
|
|
|
|
goto clean_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = EXIT_SUCCESS;
|
|
|
|
|
|
|
|
clean_up:
|
|
|
|
|
|
|
|
SLUNKCRYPT_SAFE_FREE(ctx);
|
|
|
|
|
|
|
|
if (buffer)
|
|
|
|
{
|
|
|
|
slunkcrypt_bzero(buffer, LENGTH);
|
|
|
|
free(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-04-07 00:15:07 +02:00
|
|
|
int run_selftest_routine(const size_t thread_count)
|
2021-04-18 15:32:37 +02:00
|
|
|
{
|
2022-04-02 17:27:48 +02:00
|
|
|
static const size_t ITERATIONS = 2U;
|
2021-04-18 15:32:37 +02:00
|
|
|
static const uint64_t TEST_NONCE[] = { 0x243F6A8885A308D3, 0x13198A2E03707344 };
|
2022-04-02 17:27:48 +02:00
|
|
|
|
2021-04-18 15:32:37 +02:00
|
|
|
const struct
|
|
|
|
{
|
|
|
|
const char* text;
|
2022-10-13 02:26:51 +02:00
|
|
|
uint64_t check_orig, check_encr[2U][2U];
|
2021-04-18 15:32:37 +02:00
|
|
|
}
|
|
|
|
TEST_STAGE[] =
|
|
|
|
{
|
2022-10-13 02:26:51 +02:00
|
|
|
{ TEST_DATA_0, TEST_CHCK_ORIG_0, { { TEST_CHCK_ENCR_0[0U], TEST_CHCK_ENCR_0[1U] }, { TEST_CHCK_ENCR_0[2U], TEST_CHCK_ENCR_0[3U] } } },
|
|
|
|
{ TEST_DATA_1, TEST_CHCK_ORIG_1, { { TEST_CHCK_ENCR_1[0U], TEST_CHCK_ENCR_1[1U] }, { TEST_CHCK_ENCR_1[2U], TEST_CHCK_ENCR_1[3U] } } },
|
|
|
|
{ TEST_DATA_2, TEST_CHCK_ORIG_2, { { TEST_CHCK_ENCR_2[0U], TEST_CHCK_ENCR_2[1U] }, { TEST_CHCK_ENCR_2[2U], TEST_CHCK_ENCR_2[3U] } } },
|
|
|
|
{ TEST_DATA_3, TEST_CHCK_ORIG_3, { { TEST_CHCK_ENCR_3[0U], TEST_CHCK_ENCR_3[1U] }, { TEST_CHCK_ENCR_3[2U], TEST_CHCK_ENCR_3[3U] } } }
|
2021-04-18 15:32:37 +02:00
|
|
|
};
|
|
|
|
|
2022-10-13 02:26:51 +02:00
|
|
|
const size_t total = ARRAY_SIZE(TEST_NONCE) * (ITERATIONS + (ITERATIONS * ARRAY_SIZE(TEST_STAGE)));
|
2022-04-02 17:27:48 +02:00
|
|
|
size_t count = 0U;
|
|
|
|
|
|
|
|
FPRINTF(stderr, T("Self-test is in progress, please be patient... stage %2u/%2u "), 0U, (unsigned)total);
|
2021-04-18 15:32:37 +02:00
|
|
|
fflush(stderr);
|
|
|
|
|
2022-04-02 17:27:48 +02:00
|
|
|
for (size_t i = 0U; i < ARRAY_SIZE(TEST_STAGE); ++i)
|
2021-04-18 15:32:37 +02:00
|
|
|
{
|
2022-10-13 02:26:51 +02:00
|
|
|
for (size_t j = 0U; j < ITERATIONS; ++j)
|
2021-04-18 15:32:37 +02:00
|
|
|
{
|
2022-10-13 02:26:51 +02:00
|
|
|
const slunkparam_t param = { SLUNKCRYPT_PARAM_VERSION, thread_count, (j > 0) };
|
|
|
|
for (size_t k = 0U; k < ARRAY_SIZE(TEST_NONCE); ++k)
|
2021-04-18 15:32:37 +02:00
|
|
|
{
|
2022-10-13 02:26:51 +02:00
|
|
|
FPRINTF(stderr, T("\b\b\b\b\b\b%2u/%2u "), (unsigned)++count, (unsigned)total);
|
|
|
|
fflush(stderr);
|
|
|
|
if (run_testcase(TEST_STAGE[i].text, TEST_NONCE[k], TEST_STAGE[i].check_orig, TEST_STAGE[i].check_encr[j][k], ¶m) != EXIT_SUCCESS)
|
|
|
|
{
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2021-04-18 15:32:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-13 02:26:51 +02:00
|
|
|
const slunkparam_t param = { SLUNKCRYPT_PARAM_VERSION, thread_count, 0 };
|
2022-04-02 17:27:48 +02:00
|
|
|
for (size_t i = 0U; i < ITERATIONS; ++i)
|
|
|
|
{
|
|
|
|
for (size_t j = 0U; j < ARRAY_SIZE(TEST_NONCE); ++j)
|
|
|
|
{
|
|
|
|
FPRINTF(stderr, T("\b\b\b\b\b\b%2u/%2u "), (unsigned)++count, (unsigned)total);
|
|
|
|
fflush(stderr);
|
2022-04-07 00:15:07 +02:00
|
|
|
if (run_stresstest(TEST_NONCE[j], ¶m) != EXIT_SUCCESS)
|
2022-04-02 17:27:48 +02:00
|
|
|
{
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FPRINTF(stderr, T("\b\b\b\b\b\b%2u/%2u\n\nCompleted successfully.\n\n"), (unsigned)total, (unsigned)total);
|
2021-04-18 15:32:37 +02:00
|
|
|
fflush(stderr);
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|