diff --git a/src/dyn_crypto.c b/src/dyn_crypto.c index 687a71f21..8c7531448 100644 --- a/src/dyn_crypto.c +++ b/src/dyn_crypto.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "dyn_core.h" #include "dyn_crypto.h" @@ -264,20 +265,39 @@ base64_decode(const char *b64message, const size_t length, unsigned char } */ -rstatus_t aes_encrypt(const unsigned char *msg, size_t msg_len, - unsigned char **enc_msg, unsigned char *arg_aes_key) { +rstatus_t aes_encrypt(const unsigned char *original_msg, + size_t original_msg_len, unsigned char **enc_msg, + unsigned char *arg_aes_key) { int block_len = 0; int enc_msg_len = 0; + // Create a new plaintext, with an additional block of randomness prepended + // as an explicit initialization vector. + size_t msg_len = original_msg_len + AES_BLOCK_SIZE; + unsigned char *msg = malloc(msg_len); + + if (RAND_bytes(msg, AES_BLOCK_SIZE) == 0) { + log_debug(LOG_VERB, + "RAND_bytes failed to generate an explicit iv for : '%.*s':", + original_msg_len, + original_msg); + return DN_ERROR; + } + + int i; + for (i = 0; i < original_msg_len; i++) { + msg[i+AES_BLOCK_SIZE] = original_msg[i]; + } + + // Malloc enough room for the new plaintext and the final block of padding. *enc_msg = (unsigned char *)malloc(msg_len + AES_BLOCK_SIZE); if (*enc_msg == NULL) return DN_ERROR; - // if(!EVP_EncryptInit_ex(aes_encrypt_ctx, aes_cipher, NULL, arg_aes_key, - // aes_iv)) { if (!EVP_EncryptInit_ex(aes_encrypt_ctx, aes_cipher, NULL, arg_aes_key, arg_aes_key)) { log_debug(LOG_VERB, "This is bad data in EVP_EncryptInit_ex : '%.*s'", msg_len, msg); + free(msg); return DN_ERROR; } @@ -285,6 +305,7 @@ rstatus_t aes_encrypt(const unsigned char *msg, size_t msg_len, (unsigned char *)msg, (int)msg_len)) { log_debug(LOG_VERB, "This is bad data in EVP_EncryptUpdate : '%.*s'", msg_len, msg); + free(msg); return DN_ERROR; } enc_msg_len += block_len; @@ -293,9 +314,12 @@ rstatus_t aes_encrypt(const unsigned char *msg, size_t msg_len, &block_len)) { log_debug(LOG_VERB, "This is bad data in EVP_EncryptFinal_ex : '%.*s'", msg_len, msg); + free(msg); return DN_ERROR; } + free(msg); + // EVP_CIPHER_CTX_cleanup(aesEncryptCtx); return enc_msg_len + block_len; @@ -308,8 +332,6 @@ rstatus_t dyn_aes_encrypt(const unsigned char *msg, size_t msg_len, ASSERT(mbuf != NULL && mbuf->last == mbuf->pos); - // if(!EVP_EncryptInit_ex(aes_encrypt_ctx, aes_cipher, NULL, arg_aes_key, - // aes_iv)) { if (!EVP_EncryptInit_ex(aes_encrypt_ctx, aes_cipher, NULL, arg_aes_key, arg_aes_key)) { loga_hexdump( @@ -362,8 +384,6 @@ rstatus_t dyn_aes_decrypt(unsigned char *enc_msg, size_t enc_msg_len, ASSERT(mbuf != NULL && mbuf->start == mbuf->pos); - // if(!EVP_DecryptInit_ex(aes_decrypt_ctx, aes_cipher, NULL, arg_aes_key, - // aes_iv)) { if (!EVP_DecryptInit_ex(aes_decrypt_ctx, aes_cipher, NULL, arg_aes_key, arg_aes_key)) { loga_hexdump( @@ -475,8 +495,6 @@ rstatus_t aes_decrypt(unsigned char *enc_msg, size_t enc_msg_len, *dec_msg = (unsigned char *)malloc(enc_msg_len); if (*dec_msg == NULL) return DN_ERROR; - // if(!EVP_DecryptInit_ex(aes_decrypt_ctx, aes_cipher, NULL, arg_aes_key, - // aes_iv)) { if (!EVP_DecryptInit_ex(aes_decrypt_ctx, aes_cipher, NULL, arg_aes_key, arg_aes_key)) { log_debug(LOG_VERB, "This is bad data in EVP_DecryptInit_ex : '%.*s'", @@ -500,6 +518,12 @@ rstatus_t aes_decrypt(unsigned char *enc_msg, size_t enc_msg_len, } dec_len += block_len; + // Drop the first block of random plaintext by shifting dec_msg over + // by one block. + dec_len -= AES_BLOCK_SIZE; + memmove(*dec_msg, *dec_msg + AES_BLOCK_SIZE, dec_len); + (*dec_msg)[dec_len] = '\0'; + // EVP_CIPHER_CTX_cleanup(aesDecryptCtx); return (int)dec_len; diff --git a/src/dyn_test.c b/src/dyn_test.c index 24e6b460a..bdab7a8e3 100644 --- a/src/dyn_test.c +++ b/src/dyn_test.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -397,7 +398,9 @@ static rstatus_t aes_test(void) { } size_t enc_msg_len = (size_t)ret; /* if success, aes_encrypt returns len */ - size_t expected_output_len = 16 * (msg_len / 16 + 1); + // Expected output is 2 blocks larger than the original msg_len, due to the + // explicit initialization vector and padding. + size_t expected_output_len = 16 * (msg_len / 16 + 2); if (enc_msg_len != expected_output_len) { log_panic("msg:'%s'\nexpected encrypted len: %lu encrypted len %lu\n\n", msg, expected_output_len, enc_msg_len); @@ -415,15 +418,43 @@ static rstatus_t aes_test(void) { if (strcmp(msg, dec_msg) != 0) { loga_hexdump(msg, strlen(msg), "Original Message:"); loga_hexdump(dec_msg, strlen(dec_msg), "Decrypted Message:"); - log_panic("encryption/Decryption mismatch"); + log_panic("encryption/decryption mismatch"); } free(enc_msg); free(dec_msg); - if ((i + 1) % 1000000 == 0) { + if ((i + 1) % (count / 10) == 0) { loga("Completed Running %lu messages", i + 1); } } + + loga("Making sure encryption is non-deterministic"); + gen_random(msg, rand() % MAX_MSG_LEN); + unsigned int msg_len = strlen(msg) + 1; + unsigned char *enc_msg_1 = NULL; + unsigned char *enc_msg_2 = NULL; + + rstatus_t ret_1 = + aes_encrypt((const unsigned char *)msg, msg_len, &enc_msg_1, aes_key); + rstatus_t ret_2 = + aes_encrypt((const unsigned char *)msg, msg_len, &enc_msg_2, aes_key); + if (ret_1 == DN_ERROR || ret_2 == DN_ERROR) { + log_panic("msg:'%s'\nencryption failed aes_key '%s'\n", msg, + aes_key_print); + return DN_ERROR; + } + + if ((size_t)ret_1 == (size_t)ret_2 && + !strncmp(enc_msg_1, enc_msg_2, (size_t)ret_1)) { + loga_hexdump(msg, strlen(msg), "Original Message:"); + loga_hexdump(enc_msg_1, (size_t)ret_1, "Encrypted Message #1:"); + loga_hexdump(enc_msg_2, (size_t)ret_2, "Encrypted Message #2:"); + log_panic("Encryption failed to be non-deterministic"); + } + + free(enc_msg_1); + free(enc_msg_2); + return DN_OK; } /**