added random header to AES and removed malloc calls
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -2,40 +2,54 @@
|
||||
#include "tlibc/std.h"
|
||||
#include "tlibc/collections/Array.h"
|
||||
#include "tlibc/string/str.h"
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_rand.h"
|
||||
|
||||
/// @brief hashes password multiple times using its own hash as salt
|
||||
/// @param password some byte array
|
||||
/// @param out_buffer u8[hash_password_out_size]
|
||||
/// @param iterations number of iterations
|
||||
/// @return Array<u8, 32>
|
||||
Array hash_password(str password, i32 iterations);
|
||||
void hash_password(str password, u8* out_buffer, i32 iterations);
|
||||
#define hash_password_out_size 32
|
||||
|
||||
|
||||
typedef struct EncryptedBlockInfo {
|
||||
u32 padding_size;
|
||||
u8 padding_size;
|
||||
u32 _reserved;
|
||||
u64 __reserved;
|
||||
} EncryptedBlockInfo;
|
||||
} __attribute__((aligned(16))) EncryptedBlockInfo;
|
||||
|
||||
typedef struct EncryptorAES EncryptorAES;
|
||||
// must be multiple of 16
|
||||
#define __AES_BUFFER_SIZE 512
|
||||
// must be multiple of 16
|
||||
#define __AES_RANDOM_BYTES_N 16
|
||||
|
||||
typedef struct EncryptorAES {
|
||||
br_aes_ct64_cbcenc_keys enc_ctx;
|
||||
br_hmac_drbg_context rng_ctx;
|
||||
u8 buf[__AES_BUFFER_SIZE];
|
||||
u8 iv[16];
|
||||
} EncryptorAES;
|
||||
|
||||
/// @param key Array<u8, 16 | 24 | 32>
|
||||
EncryptorAES* EncryptorAES_create(Array key);
|
||||
|
||||
void EncryptorAES_destroy(EncryptorAES* ptr);
|
||||
void EncryptorAES_create(EncryptorAES* ptr, Array key);
|
||||
|
||||
/// @brief Encrypts `src` and writes output to `dst`.
|
||||
/// @param src array of any size
|
||||
/// @param dst array of size >= EncryptorAES_calcDstSize(src.size)
|
||||
void EncryptorAES_encrypt(EncryptorAES* ptr, Array src, Array dst);
|
||||
|
||||
#define EncryptorAES_calcDstSize(SRC_SIZE) (ALIGN_TO(SRC_SIZE, 16) + sizeof(EncryptedBlockInfo))
|
||||
#define EncryptorAES_calcDstSize(SRC_SIZE) (ALIGN_TO(SRC_SIZE, 16) + __AES_RANDOM_BYTES_N + sizeof(EncryptedBlockInfo))
|
||||
|
||||
typedef struct DecryptorAES DecryptorAES;
|
||||
|
||||
typedef struct DecryptorAES {
|
||||
br_aes_ct64_cbcdec_keys dec_ctx;
|
||||
u8 buf[__AES_BUFFER_SIZE];
|
||||
u8 iv[16];
|
||||
} DecryptorAES;
|
||||
|
||||
/// @param key Array<u8, 16 | 24 | 32>
|
||||
DecryptorAES* DecryptorAES_create(Array key);
|
||||
|
||||
void DecryptorAES_destroy(DecryptorAES* ptr);
|
||||
void DecryptorAES_create(DecryptorAES* ptr, Array key);
|
||||
|
||||
/// @brief Decrypts `src` and writes output to `dst`.
|
||||
/// @param src array of any size
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
#include "cryptography.h"
|
||||
#include "BearSSL/inc/bearssl_hash.h"
|
||||
#include "bearssl_hash.h"
|
||||
#include "assert.h"
|
||||
|
||||
Array hash_password(str password, i32 iterations){
|
||||
Array hash_buffer = Array_alloc(u8, br_sha256_SIZE);
|
||||
Array_memset(&hash_buffer, 0);
|
||||
void hash_password(str password, u8* out_buffer, i32 iterations){
|
||||
assert(hash_password_out_size == br_sha256_SIZE);;
|
||||
memset(out_buffer, 0, br_sha256_SIZE);
|
||||
br_sha256_context sha256_ctx;
|
||||
br_sha256_init(&sha256_ctx);
|
||||
|
||||
for(i32 i = 0; i < iterations; i++){
|
||||
br_sha256_update(&sha256_ctx, password.data, password.size);
|
||||
br_sha256_out(&sha256_ctx, hash_buffer.data);
|
||||
br_sha256_update(&sha256_ctx, hash_buffer.data, hash_buffer.size);
|
||||
br_sha256_out(&sha256_ctx, out_buffer);
|
||||
br_sha256_update(&sha256_ctx, out_buffer, hash_password_out_size);
|
||||
}
|
||||
br_sha256_out(&sha256_ctx, hash_buffer.data);
|
||||
|
||||
return hash_buffer;
|
||||
br_sha256_out(&sha256_ctx, out_buffer);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user