140 lines
6.4 KiB
C
140 lines
6.4 KiB
C
#pragma once
|
|
#include "tlibc/collections/Array.h"
|
|
#include "tlibc/errors.h"
|
|
#include "tlibc/magic.h"
|
|
#include "bearssl_block.h"
|
|
#include "cryptography.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// AES.c //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define AESBlockEncryptor_DEFAULT_CLASS (&br_aes_big_cbcenc_vtable)
|
|
#define AESBlockDecryptor_DEFAULT_CLASS (&br_aes_big_cbcdec_vtable)
|
|
#define AESStream_DEFAULT_CLASS (&br_aes_big_ctr_vtable)
|
|
|
|
|
|
#define __AES_BLOCK_KEY_CHECKSUM_SIZE br_sha256_SIZE
|
|
typedef struct EncryptedBlockHeader {
|
|
u8 key_checksum[__AES_BLOCK_KEY_CHECKSUM_SIZE];
|
|
u8 padding_size;
|
|
} ATTRIBUTE_ALIGNED(16) EncryptedBlockHeader;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// AESBlockEncryptor //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define __AES_BLOCK_IV_SIZE 16
|
|
// must be multiple of 16
|
|
#define __AES_BUFFER_SIZE 512
|
|
|
|
typedef struct AESBlockEncryptor {
|
|
const br_block_cbcenc_class* enc_class;
|
|
u8 enc_keys[sizeof(br_aes_big_cbcenc_keys)];
|
|
u8 buf[__AES_BUFFER_SIZE];
|
|
u8 iv[__AES_BLOCK_IV_SIZE];
|
|
u8 key_checksum[__AES_BLOCK_KEY_CHECKSUM_SIZE];
|
|
br_hmac_drbg_context rng_ctx;
|
|
} AESBlockEncryptor;
|
|
|
|
/// @param key supported sizes: 16, 24, 32
|
|
/// @param enc_class &br_aes_XXX_cbcenc_vtable
|
|
void AESBlockEncryptor_construct(AESBlockEncryptor* ptr, Array(u8) key, const br_block_cbcenc_class* enc_class);
|
|
|
|
/// @param key supported sizes: 16, 24, 32
|
|
void AESBlockEncryptor_changeKey(AESBlockEncryptor* ptr, Array(u8) key);
|
|
|
|
/// @brief Encrypts a complete message. For part-by-part encryption use AESStreamEncryptor.
|
|
/// @param src array of any size
|
|
/// @param dst array of size >= AESBlockEncryptor_calcDstSize(src.size)
|
|
/// @return size of encrypted data
|
|
Result(u32) AESBlockEncryptor_encrypt(AESBlockEncryptor* ptr, Array(u8) src, Array(u8) dst);
|
|
|
|
#define AESBlockEncryptor_calcDstSize(SRC_SIZE) (__AES_BLOCK_IV_SIZE + sizeof(EncryptedBlockHeader) + ALIGN_TO(SRC_SIZE, 16))
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// AESBlockDecryptor //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct AESBlockDecryptor {
|
|
const br_block_cbcdec_class* dec_class;
|
|
u8 dec_keys[sizeof(br_aes_big_cbcdec_keys)];
|
|
u8 buf[__AES_BUFFER_SIZE];
|
|
u8 iv[__AES_BLOCK_IV_SIZE];
|
|
u8 key_checksum[__AES_BLOCK_KEY_CHECKSUM_SIZE];
|
|
} AESBlockDecryptor;
|
|
|
|
/// @param key supported sizes: 16, 24, 32
|
|
/// @param dec_class &br_aes_XXX_cbcdec_vtable
|
|
void AESBlockDecryptor_construct(AESBlockDecryptor* ptr, Array(u8) key, const br_block_cbcdec_class* dec_class);
|
|
|
|
/// @param key supported sizes: 16, 24, 32
|
|
void AESBlockDecryptor_changeKey(AESBlockDecryptor* ptr, Array(u8) key);
|
|
|
|
/// @brief Decrypts a complete message. For part-by-part decryption use AESStreamEncryptor.
|
|
/// @param src array of size at least AESBlockEncryptor_calcDstSize(0). Size must be multiple of 16.
|
|
/// @param dst array of size >= src.size
|
|
/// @return size of decrypted data
|
|
Result(u32) AESBlockDecryptor_decrypt(AESBlockDecryptor* ptr, Array(u8) src, Array(u8) dst);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// AESStreamEncryptor //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define __AES_STREAM_IV_SIZE 12
|
|
|
|
typedef struct AESStreamEncryptor {
|
|
const br_block_ctr_class* ctr_class;
|
|
u8 ctr_keys[sizeof(br_aes_big_ctr_keys)];
|
|
u8 buf[__AES_BUFFER_SIZE];
|
|
u8 iv[__AES_STREAM_IV_SIZE];
|
|
u8 key_checksum[__AES_BLOCK_KEY_CHECKSUM_SIZE];
|
|
u32 block_counter;
|
|
} AESStreamEncryptor;
|
|
|
|
/// @warning If you start from not first block in sequence (example: to continue a previously interrupted operation) set correct values for ptr->block_counter and ptr->iv or encryption/decryption will produce incorrect data.
|
|
/// @param key supported sizes: 16, 24, 32
|
|
/// @param dec_class &br_aes_XXX_ctr_vtable
|
|
void AESStreamEncryptor_construct(AESStreamEncryptor* ptr, Array(u8) key, const br_block_ctr_class* ctr_class);
|
|
|
|
/// @param key supported sizes: 16, 24, 32
|
|
void AESStreamEncryptor_changeKey(AESStreamEncryptor* ptr, Array(u8) key);
|
|
|
|
/// use this only at the beginning of the stream
|
|
#define AESStreamEncryptor_calcDstSize(src_size) (__AES_STREAM_IV_SIZE + __AES_BLOCK_KEY_CHECKSUM_SIZE + src_size)
|
|
|
|
/// @brief If ptr->block_counter == 0, writes random IV to `dst`. After that writes encrypted data to dst.
|
|
/// @param src array of any size
|
|
/// @param dst array of size >= `AESStreamEncryptor_calcDstSize(src.size)` for first block and `src.size `for other blocks
|
|
/// @return size of encrypted data
|
|
Result(u32) AESStreamEncryptor_encrypt(AESStreamEncryptor* ptr, Array(u8) src, Array(u8) dst);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// AESStreamDecryptor //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct AESStreamDecryptor {
|
|
const br_block_ctr_class* ctr_class;
|
|
u8 ctr_keys[sizeof(br_aes_big_ctr_keys)];
|
|
u8 buf[__AES_BUFFER_SIZE];
|
|
u8 iv[__AES_STREAM_IV_SIZE];
|
|
u8 key_checksum[__AES_BLOCK_KEY_CHECKSUM_SIZE];
|
|
u32 block_counter;
|
|
} AESStreamDecryptor;
|
|
|
|
/// @warning If you start from not first block in sequence (example: to continue a previously interrupted operation) set correct values for ptr->block_counter and ptr->iv or encryption/decryption will produce incorrect data.
|
|
/// @param key supported sizes: 16, 24, 32
|
|
/// @param dec_class &br_aes_XXX_ctr_vtable
|
|
void AESStreamDecryptor_construct(AESStreamDecryptor* ptr, Array(u8) key, const br_block_ctr_class* ctr_class);
|
|
|
|
/// @param key supported sizes: 16, 24, 32
|
|
void AESStreamDecryptor_changeKey(AESStreamDecryptor* ptr, Array(u8) key);
|
|
|
|
/// @brief Reads IV from `src`, then decrypts data and writes it to dst
|
|
/// @param src array of any size
|
|
/// @param dst array of size >= src.size
|
|
/// @return size of decrypted data
|
|
Result(u32) AESStreamDecryptor_decrypt(AESStreamDecryptor* ptr, Array(u8) src, Array(u8) dst);
|