2017-11-03 13:57:58 -04:00
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Test Block Cipher
|
|
|
|
***********************************************************************************************************************************/
|
2017-12-22 18:36:36 -05:00
|
|
|
|
2017-11-03 13:57:58 -04:00
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Data for testing
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
#define TEST_CIPHER "aes-256-cbc"
|
|
|
|
#define TEST_PASS "areallybadpassphrase"
|
|
|
|
#define TEST_PASS_SIZE strlen(TEST_PASS)
|
|
|
|
#define TEST_PLAINTEXT "plaintext"
|
|
|
|
#define TEST_DIGEST "sha256"
|
|
|
|
#define TEST_BUFFER_SIZE 256
|
|
|
|
|
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Test Run
|
|
|
|
***********************************************************************************************************************************/
|
2018-01-31 18:22:25 -05:00
|
|
|
void
|
2018-08-03 19:19:14 -04:00
|
|
|
testRun(void)
|
2017-11-03 13:57:58 -04:00
|
|
|
{
|
2018-05-18 11:57:32 -04:00
|
|
|
FUNCTION_HARNESS_VOID();
|
|
|
|
|
2018-09-16 14:15:21 -04:00
|
|
|
// *****************************************************************************************************************************
|
2017-11-03 13:57:58 -04:00
|
|
|
if (testBegin("blockCipherNew() and blockCipherFree()"))
|
|
|
|
{
|
|
|
|
// Cipher and digest errors
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_ERROR(
|
|
|
|
cipherBlockNew(
|
2017-11-06 22:55:34 -05:00
|
|
|
cipherModeEncrypt, BOGUS_STR, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL), AssertError,
|
|
|
|
"unable to load cipher 'BOGUS'");
|
2017-11-03 13:57:58 -04:00
|
|
|
TEST_ERROR(
|
|
|
|
cipherBlockNew(
|
2017-11-06 22:55:34 -05:00
|
|
|
cipherModeEncrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, BOGUS_STR), AssertError,
|
2017-11-03 13:57:58 -04:00
|
|
|
"unable to load digest 'BOGUS'");
|
|
|
|
|
|
|
|
// Initialization of object
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2017-11-06 22:55:34 -05:00
|
|
|
CipherBlock *cipherBlock = cipherBlockNew(cipherModeEncrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
2017-11-03 13:57:58 -04:00
|
|
|
TEST_RESULT_STR(memContextName(cipherBlock->memContext), "cipherBlock", "mem context name is valid");
|
|
|
|
TEST_RESULT_INT(cipherBlock->mode, cipherModeEncrypt, "mode is valid");
|
|
|
|
TEST_RESULT_INT(cipherBlock->passSize, TEST_PASS_SIZE, "passphrase size is valid");
|
|
|
|
TEST_RESULT_BOOL(memcmp(cipherBlock->pass, TEST_PASS, TEST_PASS_SIZE) == 0, true, "passphrase is valid");
|
|
|
|
TEST_RESULT_BOOL(cipherBlock->saltDone, false, "salt done is false");
|
|
|
|
TEST_RESULT_BOOL(cipherBlock->processDone, false, "process done is false");
|
|
|
|
TEST_RESULT_INT(cipherBlock->headerSize, 0, "header size is 0");
|
|
|
|
TEST_RESULT_PTR_NE(cipherBlock->cipher, NULL, "cipher is set");
|
|
|
|
TEST_RESULT_PTR_NE(cipherBlock->digest, NULL, "digest is set");
|
|
|
|
TEST_RESULT_PTR(cipherBlock->cipherContext, NULL, "cipher context is not set");
|
|
|
|
memContextFree(cipherBlock->memContext);
|
|
|
|
}
|
|
|
|
|
2018-09-16 14:15:21 -04:00
|
|
|
// *****************************************************************************************************************************
|
2017-11-03 13:57:58 -04:00
|
|
|
if (testBegin("Encrypt and Decrypt"))
|
|
|
|
{
|
2017-11-06 22:55:34 -05:00
|
|
|
unsigned char encryptBuffer[TEST_BUFFER_SIZE];
|
2018-03-02 12:07:12 -05:00
|
|
|
size_t encryptSize = 0;
|
2017-11-06 22:55:34 -05:00
|
|
|
unsigned char decryptBuffer[TEST_BUFFER_SIZE];
|
2018-03-02 12:07:12 -05:00
|
|
|
size_t decryptSize = 0;
|
2017-11-03 13:57:58 -04:00
|
|
|
|
|
|
|
// Encrypt
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2017-11-06 22:55:34 -05:00
|
|
|
CipherBlock *blockEncrypt = cipherBlockNew(
|
|
|
|
cipherModeEncrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2017-11-06 22:55:34 -05:00
|
|
|
TEST_RESULT_INT(
|
|
|
|
cipherBlockProcessSize(blockEncrypt, strlen(TEST_PLAINTEXT)),
|
|
|
|
strlen(TEST_PLAINTEXT) + EVP_MAX_BLOCK_LENGTH + CIPHER_BLOCK_MAGIC_SIZE + PKCS5_SALT_LEN, "check process size");
|
|
|
|
|
|
|
|
encryptSize = cipherBlockProcess(blockEncrypt, (unsigned char *)TEST_PLAINTEXT, strlen(TEST_PLAINTEXT), encryptBuffer);
|
2017-11-03 13:57:58 -04:00
|
|
|
|
|
|
|
TEST_RESULT_BOOL(blockEncrypt->saltDone, true, "salt done is true");
|
|
|
|
TEST_RESULT_BOOL(blockEncrypt->processDone, true, "process done is true");
|
|
|
|
TEST_RESULT_INT(blockEncrypt->headerSize, 0, "header size is 0");
|
|
|
|
TEST_RESULT_INT(encryptSize, CIPHER_BLOCK_HEADER_SIZE, "cipher size is header len");
|
|
|
|
|
|
|
|
TEST_RESULT_INT(
|
|
|
|
cipherBlockProcessSize(blockEncrypt, strlen(TEST_PLAINTEXT)),
|
2017-11-06 22:55:34 -05:00
|
|
|
strlen(TEST_PLAINTEXT) + EVP_MAX_BLOCK_LENGTH, "check process size");
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2017-11-06 22:55:34 -05:00
|
|
|
encryptSize += cipherBlockProcess(
|
|
|
|
blockEncrypt, (unsigned char *)TEST_PLAINTEXT, strlen(TEST_PLAINTEXT), encryptBuffer + encryptSize);
|
2017-11-03 13:57:58 -04:00
|
|
|
TEST_RESULT_INT(
|
2018-08-14 16:08:58 -04:00
|
|
|
encryptSize, CIPHER_BLOCK_HEADER_SIZE + (size_t)EVP_CIPHER_block_size(blockEncrypt->cipher),
|
2017-11-03 13:57:58 -04:00
|
|
|
"cipher size increases by one block");
|
|
|
|
|
|
|
|
encryptSize += cipherBlockFlush(blockEncrypt, encryptBuffer + encryptSize);
|
|
|
|
TEST_RESULT_INT(
|
2018-08-14 16:08:58 -04:00
|
|
|
encryptSize, CIPHER_BLOCK_HEADER_SIZE + (size_t)(EVP_CIPHER_block_size(blockEncrypt->cipher) * 2),
|
2017-11-03 13:57:58 -04:00
|
|
|
"cipher size increases by one block on flush");
|
|
|
|
|
|
|
|
cipherBlockFree(blockEncrypt);
|
|
|
|
|
|
|
|
// Decrypt in one pass
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2017-11-06 22:55:34 -05:00
|
|
|
CipherBlock *blockDecrypt = cipherBlockNew(
|
|
|
|
cipherModeDecrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
|
|
|
|
|
|
|
TEST_RESULT_INT(
|
2017-12-22 18:36:36 -05:00
|
|
|
cipherBlockProcessSize(blockDecrypt, encryptSize),
|
2017-11-06 22:55:34 -05:00
|
|
|
encryptSize + EVP_MAX_BLOCK_LENGTH, "check process size");
|
2017-11-03 13:57:58 -04:00
|
|
|
|
|
|
|
decryptSize = cipherBlockProcess(blockDecrypt, encryptBuffer, encryptSize, decryptBuffer);
|
|
|
|
TEST_RESULT_INT(decryptSize, EVP_CIPHER_block_size(blockDecrypt->cipher), "decrypt size is one block");
|
|
|
|
|
|
|
|
decryptSize += cipherBlockFlush(blockDecrypt, decryptBuffer + decryptSize);
|
|
|
|
TEST_RESULT_INT(decryptSize, strlen(TEST_PLAINTEXT) * 2, "check final decrypt size");
|
|
|
|
|
|
|
|
decryptBuffer[decryptSize] = 0;
|
|
|
|
TEST_RESULT_STR(decryptBuffer, (TEST_PLAINTEXT TEST_PLAINTEXT), "check final decrypt buffer");
|
|
|
|
|
2017-12-22 18:36:36 -05:00
|
|
|
cipherBlockFree(blockDecrypt);
|
|
|
|
|
2017-11-03 13:57:58 -04:00
|
|
|
// Decrypt in small chunks to test buffering
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2017-11-06 22:55:34 -05:00
|
|
|
blockDecrypt = cipherBlockNew(cipherModeDecrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
2017-11-03 13:57:58 -04:00
|
|
|
|
|
|
|
decryptSize = 0;
|
|
|
|
memset(decryptBuffer, 0, TEST_BUFFER_SIZE);
|
|
|
|
|
|
|
|
decryptSize = cipherBlockProcess(blockDecrypt, encryptBuffer, CIPHER_BLOCK_MAGIC_SIZE, decryptBuffer);
|
|
|
|
TEST_RESULT_INT(decryptSize, 0, "no decrypt since header read is not complete");
|
|
|
|
TEST_RESULT_BOOL(blockDecrypt->saltDone, false, "salt done is false");
|
|
|
|
TEST_RESULT_BOOL(blockDecrypt->processDone, false, "process done is false");
|
|
|
|
TEST_RESULT_INT(blockDecrypt->headerSize, CIPHER_BLOCK_MAGIC_SIZE, "check header size");
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
memcmp(blockDecrypt->header, CIPHER_BLOCK_MAGIC, CIPHER_BLOCK_MAGIC_SIZE) == 0, true, "check header magic");
|
|
|
|
|
|
|
|
decryptSize += cipherBlockProcess(
|
|
|
|
blockDecrypt, encryptBuffer + CIPHER_BLOCK_MAGIC_SIZE, PKCS5_SALT_LEN, decryptBuffer + decryptSize);
|
|
|
|
TEST_RESULT_INT(decryptSize, 0, "no decrypt since no data processed yet");
|
|
|
|
TEST_RESULT_BOOL(blockDecrypt->saltDone, true, "salt done is true");
|
|
|
|
TEST_RESULT_BOOL(blockDecrypt->processDone, false, "process done is false");
|
|
|
|
TEST_RESULT_INT(blockDecrypt->headerSize, CIPHER_BLOCK_MAGIC_SIZE, "check header size (not increased)");
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
memcmp(
|
|
|
|
blockDecrypt->header + CIPHER_BLOCK_MAGIC_SIZE, encryptBuffer + CIPHER_BLOCK_MAGIC_SIZE,
|
|
|
|
PKCS5_SALT_LEN) == 0,
|
|
|
|
true, "check header salt");
|
|
|
|
|
|
|
|
decryptSize += cipherBlockProcess(
|
|
|
|
blockDecrypt, encryptBuffer + CIPHER_BLOCK_HEADER_SIZE, encryptSize - CIPHER_BLOCK_HEADER_SIZE,
|
|
|
|
decryptBuffer + decryptSize);
|
|
|
|
TEST_RESULT_INT(decryptSize, EVP_CIPHER_block_size(blockDecrypt->cipher), "decrypt size is one block");
|
|
|
|
|
|
|
|
decryptSize += cipherBlockFlush(blockDecrypt, decryptBuffer + decryptSize);
|
|
|
|
TEST_RESULT_INT(decryptSize, strlen(TEST_PLAINTEXT) * 2, "check final decrypt size");
|
|
|
|
|
|
|
|
decryptBuffer[decryptSize] = 0;
|
|
|
|
TEST_RESULT_STR(decryptBuffer, (TEST_PLAINTEXT TEST_PLAINTEXT), "check final decrypt buffer");
|
|
|
|
|
2017-12-22 18:36:36 -05:00
|
|
|
cipherBlockFree(blockDecrypt);
|
|
|
|
|
2017-11-03 13:57:58 -04:00
|
|
|
// Encrypt zero byte file and decrypt it
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2017-11-06 22:55:34 -05:00
|
|
|
blockEncrypt = cipherBlockNew(cipherModeEncrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
TEST_RESULT_INT(cipherBlockProcess(blockEncrypt, decryptBuffer, 0, encryptBuffer), 16, "process header");
|
2017-11-03 13:57:58 -04:00
|
|
|
TEST_RESULT_INT(cipherBlockFlush(blockEncrypt, encryptBuffer + 16), 16, "flush remaining bytes");
|
|
|
|
|
2017-12-22 18:36:36 -05:00
|
|
|
cipherBlockFree(blockEncrypt);
|
|
|
|
|
2017-11-06 22:55:34 -05:00
|
|
|
blockDecrypt = cipherBlockNew(cipherModeDecrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
2017-11-03 13:57:58 -04:00
|
|
|
|
|
|
|
TEST_RESULT_INT(cipherBlockProcess(blockDecrypt, encryptBuffer, 32, decryptBuffer), 0, "0 bytes processed");
|
|
|
|
TEST_RESULT_INT(cipherBlockFlush(blockDecrypt, decryptBuffer), 0, "0 bytes on flush");
|
|
|
|
|
2017-12-22 18:36:36 -05:00
|
|
|
cipherBlockFree(blockDecrypt);
|
|
|
|
|
2017-11-03 13:57:58 -04:00
|
|
|
// Invalid cipher header
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2017-11-06 22:55:34 -05:00
|
|
|
blockDecrypt = cipherBlockNew(cipherModeDecrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2017-11-06 22:55:34 -05:00
|
|
|
TEST_ERROR(
|
|
|
|
cipherBlockProcess(
|
2018-11-06 19:38:38 -05:00
|
|
|
blockDecrypt, (unsigned char *)"1234567890123456", 16, decryptBuffer), CryptoError, "cipher header invalid");
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2017-12-22 18:36:36 -05:00
|
|
|
cipherBlockFree(blockDecrypt);
|
|
|
|
|
2017-11-03 13:57:58 -04:00
|
|
|
// Invalid encrypted data cannot be flushed
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2017-11-06 22:55:34 -05:00
|
|
|
blockDecrypt = cipherBlockNew(cipherModeDecrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2017-11-06 22:55:34 -05:00
|
|
|
TEST_RESULT_INT(
|
|
|
|
cipherBlockProcess(
|
|
|
|
blockDecrypt, (unsigned char *)(CIPHER_BLOCK_MAGIC "12345678"), 16, decryptBuffer), 0, "process header");
|
|
|
|
TEST_RESULT_INT(
|
|
|
|
cipherBlockProcess(
|
|
|
|
blockDecrypt, (unsigned char *)"1234567890123456", 16, decryptBuffer), 0, "process 0 bytes");
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2018-11-06 19:38:38 -05:00
|
|
|
TEST_ERROR(cipherBlockFlush(blockDecrypt, decryptBuffer), CryptoError, "unable to flush");
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2017-12-22 18:36:36 -05:00
|
|
|
cipherBlockFree(blockDecrypt);
|
|
|
|
|
2017-11-03 13:57:58 -04:00
|
|
|
// File with no header should not flush
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2017-11-06 22:55:34 -05:00
|
|
|
blockDecrypt = cipherBlockNew(cipherModeDecrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
TEST_RESULT_INT(cipherBlockProcess(blockDecrypt, encryptBuffer, 0, decryptBuffer), 0, "no header processed");
|
2018-11-06 19:38:38 -05:00
|
|
|
TEST_ERROR(cipherBlockFlush(blockDecrypt, decryptBuffer), CryptoError, "cipher header missing");
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2017-12-22 18:36:36 -05:00
|
|
|
cipherBlockFree(blockDecrypt);
|
|
|
|
|
2017-11-03 13:57:58 -04:00
|
|
|
// File with header only should error
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2017-11-06 22:55:34 -05:00
|
|
|
blockDecrypt = cipherBlockNew(cipherModeDecrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
2017-11-03 13:57:58 -04:00
|
|
|
|
2017-11-06 22:55:34 -05:00
|
|
|
TEST_RESULT_INT(
|
|
|
|
cipherBlockProcess(
|
|
|
|
blockDecrypt, (unsigned char *)(CIPHER_BLOCK_MAGIC "12345678"), 16, decryptBuffer), 0, "0 bytes processed");
|
2018-11-06 19:38:38 -05:00
|
|
|
TEST_ERROR(cipherBlockFlush(blockDecrypt, decryptBuffer), CryptoError, "unable to flush");
|
2017-12-22 18:36:36 -05:00
|
|
|
|
|
|
|
cipherBlockFree(blockDecrypt);
|
2017-11-03 13:57:58 -04:00
|
|
|
}
|
2017-12-22 18:36:36 -05:00
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
FUNCTION_HARNESS_RESULT_VOID();
|
2017-11-03 13:57:58 -04:00
|
|
|
}
|