added random header to AES and removed malloc calls

This commit is contained in:
2025-07-24 05:47:18 +03:00
parent e0646139e3
commit 664ff91e63
7 changed files with 124 additions and 140 deletions

View File

@@ -1,125 +1,95 @@
#include "cryptography.h"
#include "BearSSL/inc/bearssl_block.h"
#include <assert.h>
#include "tlibc/time.h"
// size must be multiple of 16
#define __AES_BUFFER_SIZE 256
typedef struct EncryptorAES {
br_aes_ct64_cbcenc_keys enc_ctx;
Array buf;
Array iv;
} EncryptorAES;
typedef struct DecryptorAES {
br_aes_ct64_cbcdec_keys dec_ctx;
Array buf;
Array iv;
} DecryptorAES;
EncryptorAES* EncryptorAES_create(Array key){
void EncryptorAES_create(EncryptorAES* ptr, Array key){
assert(key.size == 16 || key.size == 24 || key.size == 32);
EncryptorAES* ptr = (EncryptorAES*)malloc(sizeof(EncryptorAES));
br_aes_ct64_cbcenc_init(&ptr->enc_ctx, key.data, key.size);
// size must be multiple of 16
ptr->buf = Array_alloc(u8, __AES_BUFFER_SIZE);
Array_memset(&ptr->buf, 0);
// uses CLOCK_REALTIME to seed rng
nsec_t time_now = getTimeNsec();
br_hmac_drbg_init(&ptr->rng_ctx, &br_sha256_vtable, &time_now, sizeof(time_now));
// size of one SHA block (16 bytes)
ptr->iv = Array_alloc(u8, 16);
Array_memset(&ptr->iv, 0);
return ptr;
}
void EncryptorAES_destroy(EncryptorAES* ptr){
free(ptr->buf.data);
free(ptr->iv.data);
memset(ptr->buf, 0, __AES_BUFFER_SIZE);
memset(ptr->iv, 0, sizeof(ptr->iv));
}
void EncryptorAES_encrypt(EncryptorAES* ptr, Array src, Array dst){
assert(dst.size >= EncryptorAES_calcDstSize(src.size));
// write random bytes to the beginning of the buffer
br_hmac_drbg_generate(&ptr->rng_ctx, ptr->buf, __AES_RANDOM_BYTES_N);
const EncryptedBlockInfo block_info = { .padding_size = 16 - src.size % 16 };
memcpy(ptr->buf.data, &block_info, sizeof(EncryptedBlockInfo));
// encrypt this struct
br_aes_ct64_cbcenc_run(&ptr->enc_ctx, ptr->iv.data, ptr->buf.data, sizeof(EncryptedBlockInfo));
// emit EncryptedBlockInfo to beginning of result
memcpy(dst.data, ptr->buf.data, sizeof(EncryptedBlockInfo));
dst.data += sizeof(EncryptedBlockInfo);
dst.size -= sizeof(EncryptedBlockInfo);
// write struct after random_bytes
memcpy((u8*)ptr->buf + __AES_RANDOM_BYTES_N, &block_info, sizeof(EncryptedBlockInfo));
// encrypt buffer
const u32 header_size = __AES_RANDOM_BYTES_N + sizeof(EncryptedBlockInfo);
br_aes_ct64_cbcenc_run(&ptr->enc_ctx, ptr->iv, ptr->buf, header_size);
// write encrypted header to dst
memcpy(dst.data, ptr->buf, header_size);
dst.data += header_size;
dst.size -= header_size;
// write full blocks
while(src.size > ptr->buf.size){
memcpy(ptr->buf.data, src.data, ptr->buf.size);
src.data += ptr->buf.size;
src.size -= ptr->buf.size;
br_aes_ct64_cbcenc_run(&ptr->enc_ctx, ptr->iv.data, ptr->buf.data, ptr->buf.size);
memcpy(dst.data, ptr->buf.data, ptr->buf.size);
dst.data += ptr->buf.size;
dst.size -= ptr->buf.size;
while(src.size > __AES_BUFFER_SIZE){
memcpy(ptr->buf, src.data, __AES_BUFFER_SIZE);
src.data += __AES_BUFFER_SIZE;
src.size -= __AES_BUFFER_SIZE;
br_aes_ct64_cbcenc_run(&ptr->enc_ctx, ptr->iv, ptr->buf, __AES_BUFFER_SIZE);
memcpy(dst.data, ptr->buf, __AES_BUFFER_SIZE);
dst.data += __AES_BUFFER_SIZE;
dst.size -= __AES_BUFFER_SIZE;
}
// write incomplete block
Array_memset(&ptr->buf, 0);
memcpy(ptr->buf.data, src.data, src.size);
memset(ptr->buf, 0, __AES_BUFFER_SIZE);
memcpy(ptr->buf, src.data, src.size);
u32 src_size_padded = src.size + block_info.padding_size;
br_aes_ct64_cbcenc_run(&ptr->enc_ctx, ptr->iv.data, ptr->buf.data, src_size_padded);
memcpy(dst.data, ptr->buf.data, src_size_padded);
br_aes_ct64_cbcenc_run(&ptr->enc_ctx, ptr->iv, ptr->buf, src_size_padded);
memcpy(dst.data, ptr->buf, src_size_padded);
}
DecryptorAES* DecryptorAES_create(Array key){
void DecryptorAES_create(DecryptorAES* ptr, Array key){
assert(key.size == 16 || key.size == 24 || key.size == 32);
DecryptorAES* ptr = (DecryptorAES*)malloc(sizeof(DecryptorAES));
br_aes_ct64_cbcdec_init(&ptr->dec_ctx, key.data, key.size);
// size must be multiple of 16
ptr->buf = Array_alloc(u8, __AES_BUFFER_SIZE);
Array_memset(&ptr->buf, 0);
// size of one SHA block (16 bytes)
ptr->iv = Array_alloc(u8, 16);
Array_memset(&ptr->iv, 0);
return ptr;
}
void DecryptorAES_destroy(DecryptorAES* ptr){
free(ptr->buf.data);
free(ptr->iv.data);
memset(ptr->buf, 0, __AES_BUFFER_SIZE);
memset(ptr->iv, 0, sizeof(ptr->iv));
}
void DecryptorAES_decrypt(DecryptorAES* ptr, Array src, Array dst, u32* decrypted_size){
assert(dst.size >= src.size);
// read EncryptedBlockInfo from beginning of data
// copy encrypted header from src to buffer
const u32 header_size = __AES_RANDOM_BYTES_N + sizeof(EncryptedBlockInfo);
memcpy(ptr->buf, src.data, header_size);
src.data += header_size;
src.size -= header_size;
// decrypt buffer
br_aes_ct64_cbcdec_run(&ptr->dec_ctx, ptr->iv, &ptr->buf, header_size);
// read EncryptedBlockInfo from buffer
EncryptedBlockInfo block_info;
memcpy(&block_info, src.data, sizeof(EncryptedBlockInfo));
src.data += sizeof(EncryptedBlockInfo);
src.size -= sizeof(EncryptedBlockInfo);
// decrypt this struct
br_aes_ct64_cbcdec_run(&ptr->dec_ctx, ptr->iv.data, &block_info, sizeof(EncryptedBlockInfo));
memcpy(&block_info, (u8*)ptr->buf + __AES_RANDOM_BYTES_N, sizeof(EncryptedBlockInfo));
*decrypted_size = src.size - block_info.padding_size;
// write full blocks
while(src.size > ptr->buf.size){
memcpy(ptr->buf.data, src.data, ptr->buf.size);
src.data += ptr->buf.size;
src.size -= ptr->buf.size;
br_aes_ct64_cbcdec_run(&ptr->dec_ctx, ptr->iv.data, ptr->buf.data, ptr->buf.size);
memcpy(dst.data, ptr->buf.data, ptr->buf.size);
dst.data += ptr->buf.size;
dst.size -= ptr->buf.size;
while(src.size > __AES_BUFFER_SIZE){
memcpy(ptr->buf, src.data, __AES_BUFFER_SIZE);
src.data += __AES_BUFFER_SIZE;
src.size -= __AES_BUFFER_SIZE;
br_aes_ct64_cbcdec_run(&ptr->dec_ctx, ptr->iv, ptr->buf, __AES_BUFFER_SIZE);
memcpy(dst.data, ptr->buf, __AES_BUFFER_SIZE);
dst.data += __AES_BUFFER_SIZE;
dst.size -= __AES_BUFFER_SIZE;
}
// write incomplete block
Array_memset(&ptr->buf, 0);
memcpy(ptr->buf.data, src.data, src.size);
memset(ptr->buf, 0, __AES_BUFFER_SIZE);
memcpy(ptr->buf, src.data, src.size);
u32 src_size_padded = src.size + block_info.padding_size;
br_aes_ct64_cbcdec_run(&ptr->dec_ctx, ptr->iv.data, ptr->buf.data, src_size_padded);
memcpy(dst.data, ptr->buf.data, src_size_padded);
br_aes_ct64_cbcdec_run(&ptr->dec_ctx, ptr->iv, ptr->buf, src_size_padded);
memcpy(dst.data, ptr->buf, src_size_padded);
}